Last active
August 29, 2015 14:05
-
-
Save czyrux/818c1331586194878d10 to your computer and use it in GitHub Desktop.
Tiny helper class for creating pools of objects in Java. Specially suitable for Android Projects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Helper class for creating pools of objects. | |
* | |
* An example use looks like this: | |
* | |
* <pre> | |
* public class MyPooledClass implements {@link PoolObject}{ | |
* | |
* private static final SynchronizedPool<MyPooledClass> sPool = new SynchronizedPool<MyPooledClass>(new MyPooledFactoryClass(), 10); | |
* | |
* public static MyPooledClass obtain() { | |
* return sPool.acquire(); | |
* } | |
* | |
* public void recycle() { | |
* sPool.release(this); | |
* } | |
* | |
* public void reset() { | |
* // reset variables | |
* } | |
* . . . | |
* | |
* static class MyPooledFactoryClass implements Pools.PoolObjectFactory<MyPooledClass> | |
* { | |
* public MyPooledClass createPoolObject() { | |
* return new MyPooledClass(); | |
* } | |
* } | |
* } | |
* </pre> | |
* | |
* @hide | |
*/ | |
public final class Pools { | |
private Pools() { | |
} | |
/** | |
* Poolable Object. It solves the problem of using a object with a obsolete | |
* state. | |
*/ | |
public interface PoolObject { | |
/** | |
* Reset object to default state | |
*/ | |
public void reset(); | |
} | |
/** | |
* Create objects for the object pool. It allows the Pool to never return a | |
* null object, even when object are not available on the Pool | |
* | |
* @param <T> | |
* The pooled type. | |
*/ | |
public interface PoolObjectFactory<T extends PoolObject> { | |
/** | |
* Creates a new object for the object pool. | |
* | |
* @return new object instance for the object pool | |
*/ | |
public T createPoolObject(); | |
} | |
/** | |
* Interface for managing a pool of objects. | |
* | |
* @param <T> | |
* The pooled type. | |
*/ | |
public interface Pool<T extends PoolObject> { | |
/** | |
* @return An instance from the pool if such is available. | |
*/ | |
public T acquire(); | |
/** | |
* Release an instance to the pool. | |
* | |
* @param instance | |
* The instance to release. | |
* @return Whether the instance was put in the pool. | |
* @throws IllegalStateException | |
* If the instance is already in the pool. | |
*/ | |
public boolean release(T instance); | |
} | |
/** | |
* Simple (non-synchronized) pool of objects. | |
* | |
* @param <T> | |
* The pooled type. | |
*/ | |
public static class SimplePool<T extends PoolObject> implements Pool<T> { | |
private final PoolObjectFactory<T> poolFactory; | |
private final PoolObject[] pool; | |
private int lastPooledIndex; | |
/** | |
* Creates a new instance. | |
* | |
* @param maxPoolSize | |
* The max pool size. | |
* @throws IllegalArgumentException | |
* If the max pool size is less than zero. | |
*/ | |
public SimplePool(int maxPoolSize) { | |
if (maxPoolSize <= 0) | |
throw new IllegalArgumentException( | |
"The max pool size must be > 0"); | |
lastPooledIndex = -1; | |
poolFactory = null; | |
pool = new PoolObject[maxPoolSize]; | |
} | |
/** | |
* Creates a new instance. If the factory is not null the Pool will | |
* never return a null object when {@link SimplePool#acquire()} is call, | |
* even if there are not objects available on the Pool | |
* | |
* @param factory | |
* the object pool factory instance. | |
* @param maxPoolSize | |
* The max pool size. | |
* @throws IllegalArgumentException | |
* If the max pool size is less than zero. | |
*/ | |
public SimplePool(PoolObjectFactory<T> factory, int maxPoolSize) { | |
if (maxPoolSize <= 0) | |
throw new IllegalArgumentException( | |
"The max pool size must be > 0"); | |
lastPooledIndex = -1; | |
poolFactory = factory; | |
pool = new PoolObject[maxPoolSize]; | |
} | |
@Override | |
@SuppressWarnings("unchecked") | |
public T acquire() { | |
T instance = null; | |
if (lastPooledIndex == -1) { | |
if (poolFactory != null) { | |
instance = (T) poolFactory.createPoolObject(); | |
} | |
} else { | |
instance = (T) pool[lastPooledIndex]; | |
instance.reset(); | |
pool[lastPooledIndex] = null; | |
lastPooledIndex--; | |
} | |
return instance; | |
} | |
@Override | |
public boolean release(T instance) { | |
if (isInPool(instance)) { | |
throw new IllegalStateException("Already in the pool!"); | |
} | |
if (lastPooledIndex < pool.length - 1) { | |
lastPooledIndex++; | |
pool[lastPooledIndex] = instance; | |
return true; | |
} | |
return false; | |
} | |
private boolean isInPool(T instance) { | |
for (int i = 0; i < lastPooledIndex; i++) { | |
if (pool[i] == instance) { | |
return true; | |
} | |
} | |
return false; | |
} | |
} | |
/** | |
* Synchronized pool of objects. | |
* | |
* @param <T> | |
* The pooled type. | |
*/ | |
public static class SynchronizedPool<T extends PoolObject> extends | |
SimplePool<T> { | |
private final Object lockObject = new Object(); | |
/** | |
* Creates a new instance. | |
* | |
* @param maxPoolSize | |
* The max pool size. | |
* @throws IllegalArgumentException | |
* If the max pool size is less than zero. | |
*/ | |
public SynchronizedPool(int maxPoolSize) { | |
super(maxPoolSize); | |
} | |
/** | |
* Creates a new instance. If the factory is not null the Pool will | |
* never return a null object when {@link SimplePool#acquire()} is call, | |
* even if there are not objects available on the Pool | |
* | |
* @param factory | |
* the object pool factory instance. | |
* @param maxPoolSize | |
* The max pool size. | |
* @throws IllegalArgumentException | |
* If the max pool size is less than zero. | |
*/ | |
public SynchronizedPool(PoolObjectFactory<T> factory, int maxPoolSize) { | |
super(factory, maxPoolSize); | |
} | |
@Override | |
public T acquire() { | |
synchronized (lockObject) { | |
return super.acquire(); | |
} | |
} | |
@Override | |
public boolean release(T element) { | |
synchronized (lockObject) { | |
return super.release(element); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment