package org.anddev.andengine.util.pool; import java.util.Collections; import java.util.Stack; import org.anddev.andengine.util.Debug; /** * @author Valentin Milea * (c) 2010 Nicolas Gramlich * (c) 2011 Zynga Inc. * * @author Nicolas Gramlich * * @since 22:19:55 - 31.08.2010 * @param <T> */ public abstract class GenericPool<T> { // =========================================================== // Constants // =========================================================== // =========================================================== // Fields // =========================================================== private final Stack<T> mAvailableItems = new Stack<T>(); private int mUnrecycledCount; private final int mGrowth; // =========================================================== // Constructors // =========================================================== public GenericPool() { this(0); } public GenericPool(final int pInitialSize) { this(pInitialSize, 1); } public GenericPool(final int pInitialSize, final int pGrowth) { if(pGrowth < 0) { throw new IllegalArgumentException("pGrowth must be at least 0!"); } this.mGrowth = pGrowth; if(pInitialSize > 0) { this.batchAllocatePoolItems(pInitialSize); } } // =========================================================== // Getter & Setter // =========================================================== public synchronized int getUnrecycledCount() { return this.mUnrecycledCount; } // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== protected abstract T onAllocatePoolItem(); // =========================================================== // Methods // =========================================================== /** * @param pItem every item passes this method just before it gets recycled. */ protected void onHandleRecycleItem(final T pItem) { } protected T onHandleAllocatePoolItem() { return this.onAllocatePoolItem(); } /** * @param pItem every item that was just obtained from the pool, passes this method. */ protected void onHandleObtainItem(final T pItem) { } public synchronized void batchAllocatePoolItems(final int pCount) { final Stack<T> availableItems = this.mAvailableItems; for(int i = pCount - 1; i >= 0; i--) { availableItems.push(this.onHandleAllocatePoolItem()); } } public synchronized T obtainPoolItem() { final T item; if(this.mAvailableItems.size() > 0) { item = this.mAvailableItems.pop(); } else { if(this.mGrowth == 1) { item = this.onHandleAllocatePoolItem(); } else { this.batchAllocatePoolItems(this.mGrowth); item = this.mAvailableItems.pop(); } Debug.i(this.getClass().getName() + "<" + item.getClass().getSimpleName() +"> was exhausted, with " + this.mUnrecycledCount + " item not yet recycled. Allocated " + this.mGrowth + " more."); } this.onHandleObtainItem(item); this.mUnrecycledCount++; return item; } public synchronized void recyclePoolItem(final T pItem) { if(pItem == null) { throw new IllegalArgumentException("Cannot recycle null item!"); } this.onHandleRecycleItem(pItem); this.mAvailableItems.push(pItem); this.mUnrecycledCount--; if(this.mUnrecycledCount < 0) { Debug.e("More items recycled than obtained!"); } } public synchronized void shufflePoolItems() { Collections.shuffle(this.mAvailableItems); } // =========================================================== // Inner and Anonymous Classes // =========================================================== }