/*
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.imagepipeline.memory;
import javax.annotation.concurrent.ThreadSafe;
import android.util.SparseIntArray;
import com.facebook.common.internal.Preconditions;
import com.facebook.common.memory.MemoryTrimmableRegistry;
/**
* A pool of byte arrays.
* The pool manages a number of byte arrays of a predefined set of sizes. This set of sizes is
* typically, but not required to be, based on powers of 2.
* The pool supports a get/release paradigm.
* On a get request, the pool attempts to find an existing byte array whose size
* is at least as big as the requested size.
* On a release request, the pool adds the byte array to the appropriate bucket.
* This byte array can then be used for a subsequent get request.
*/
@ThreadSafe
public class GenericByteArrayPool extends BasePool<byte[]> implements ByteArrayPool {
private final int[] mBucketSizes;
/**
* Creates a new instance of the GenericByteArrayPool class
* @param memoryTrimmableRegistry the memory manager to register with
* @param poolParams provider for pool parameters
* @param poolStatsTracker
*/
public GenericByteArrayPool(
MemoryTrimmableRegistry memoryTrimmableRegistry,
PoolParams poolParams,
PoolStatsTracker poolStatsTracker) {
super(memoryTrimmableRegistry, poolParams, poolStatsTracker);
final SparseIntArray bucketSizes = poolParams.bucketSizes;
mBucketSizes = new int[bucketSizes.size()];
for (int i = 0; i < bucketSizes.size(); ++i) {
mBucketSizes[i] = bucketSizes.keyAt(i);
}
initialize();
}
/**
* Gets the smallest buffer size supported by the pool
* @return the smallest buffer size supported by the pool
*/
public int getMinBufferSize() {
return mBucketSizes[0];
}
/**
* Allocate a buffer greater than or equal to the specified size
* @param bucketedSize size of the buffer requested
* @return a byte array of the specified or larger size. Null if the size is invalid
*/
@Override
protected byte[] alloc(int bucketedSize) {
return new byte[bucketedSize];
}
/**
* Frees the 'value'
* @param value the value to free
*/
@Override
protected void free(byte[] value) {
Preconditions.checkNotNull(value);
// do nothing. Let the GC take care of this
}
/**
* Gets the size in bytes for the given 'bucketed' size
* @param bucketedSize the bucketed size
* @return size in bytes
*/
@Override
protected int getSizeInBytes(int bucketedSize) {
return bucketedSize;
}
/**
* Get the 'bucketed' size for the given request size. The 'bucketed' size is a size that is
* the same or larger than the request size. We walk through our list of pre-defined bucket
* sizes, and use that to determine the smallest bucket size that is larger than the requested
* size.
* If no such 'bucketedSize' is found, then we simply return "requestSize"
* @param requestSize the logical request size
* @return the bucketed size
* @throws InvalidSizeException, if the requested size was invalid
*/
@Override
protected int getBucketedSize(int requestSize) {
int intRequestSize = requestSize;
if (intRequestSize <= 0) {
throw new InvalidSizeException(requestSize);
}
// find the smallest bucketed size that is larger than the requested size
for (int bucketedSize : mBucketSizes) {
if (bucketedSize >= intRequestSize) {
return bucketedSize;
}
}
// requested size doesn't match our existing buckets - just return the requested size
// this will eventually translate into a plain alloc/free paradigm
return requestSize;
}
/**
* Gets the bucketed size of the value
* @param value the value
* @return just the length of the value
*/
@Override
protected int getBucketedSizeForValue(byte[] value) {
Preconditions.checkNotNull(value);
return value.length;
}
}