@Override
  public void release(V value) {
    Preconditions.checkNotNull(value);

    final int bucketedSize = getBucketedSizeForValue(value);
    final int sizeInBytes = this.getSizeInBytes(bucketedSize);
    synchronized (this) {
      final Bucket<V> bucket = getBucketIfPresent(bucketedSize);
      if (!mInUseValues.remove(value)) {
        // This value was not 'known' to the pool (i.e.) allocated via the pool.
        // Something is going wrong, so let's free the value and report soft error.
        FLog.e(
            TAG,
            "release (free, value unrecognized) (object, size) = (%x, %s)",
            System.identityHashCode(value),
            bucketedSize);
        free(value);
        mPoolStatsTracker.onFree(sizeInBytes);
      } else {
        // free the value, if
        //  - pool exceeds maxSize
        //  - there is no bucket for this value
        //  - there is a bucket for this value, but it has exceeded its maxLength
        //  - the value is not reusable
        // If no bucket was found for the value, simply free it
        // We should free the value if no bucket is found, or if the bucket length cap is exceeded.
        // However, if the pool max size softcap is exceeded, it may not always be best to free
        // *this* value.
        if (bucket == null
            || bucket.isMaxLengthExceeded()
            || isMaxSizeSoftCapExceeded()
            || !isReusable(value)) {
          if (bucket != null) {
            bucket.decrementInUseCount();
          }

          if (FLog.isLoggable(FLog.VERBOSE)) {
            FLog.v(
                TAG,
                "release (free) (object, size) = (%x, %s)",
                System.identityHashCode(value),
                bucketedSize);
          }
          free(value);
          mUsed.decrement(sizeInBytes);
          mPoolStatsTracker.onFree(sizeInBytes);
        } else {
          bucket.release(value);
          mFree.increment(sizeInBytes);
          mUsed.decrement(sizeInBytes);
          mPoolStatsTracker.onValueRelease(sizeInBytes);
          if (FLog.isLoggable(FLog.VERBOSE)) {
            FLog.v(
                TAG,
                "release (reuse) (object, size) = (%x, %s)",
                System.identityHashCode(value),
                bucketedSize);
          }
        }
      }
      logStats();
    }
  }
Releases the given value to the pool. In a few cases, the value is 'freed' instead of being
released to the pool. If - the pool currently exceeds its max size OR - if the value does not
map to a bucket that's currently maintained by the pool, OR - if the bucket for the value
exceeds its maxLength, OR - if the value is not recognized by the pool then, the value is
'freed'.

@param value the value to release to the pool
imagepipeline/src/main/java/com/facebook/imagepipeline/memory/BasePool.java