in imagepipeline/src/main/java/com/facebook/imagepipeline/memory/BasePool.java [304:365]
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();
}
}