code: public boolean put(T object) {
          if (object == null) {
              throw new IllegalArgumentException("returning null object to pool");
          }
  
          while (true) {
              // 1. get the index of the next free cell
              int g = m_get.get();
              int p = m_put.get();
              if (p >= LIMIT) {
                  // this happens very seldom - once every 1**31 calls, the put
                  // index completes a full cycle.
                  // to handle this simply, we just wait for the pool to
                  // drain, and start placing objects back in the pool only when
                  // the get index completes its cycle too.
                  return false;
              }
              if (p - g >= (m_arraySize - 1)) {
                  // put index is far from the get pointer, implying full pool.
                  // note that (p >= g + m_capacity) is a bug.
                  return false;
              }
  
              // 2. conquer this cell by incrementing the put index
              if (!m_put.compareAndSet(p, p + 1)) {
                  // some other thread got here first. try again.
                  continue;
              }
  
              // 3. put the object in the cell
              int index = p % m_arraySize;
              AtomicReference<T> reference = m_array[index];
              if (reference.compareAndSet(null, object)) {
                  return true;
              }
  
              // getting here is rare. the object that was supposedly conquered
              // locally was replaced with a different object in the same cell.
          }
      }
docs: puts an object back into the pool for recycling
  
  @param object
  the pooled object
  @return true on success, false if pool is full