package org.multiverse.stms.gamma; import org.multiverse.stms.gamma.transactionalobjects.BaseGammaTxnRef; import org.multiverse.stms.gamma.transactionalobjects.CallableNode; import org.multiverse.stms.gamma.transactionalobjects.Tranlocal; import java.util.ArrayList; /** * A pool for tranlocals. The pool is not threadsafe and should be connected to a thread (can * be stored in a threadlocal). Eventually the performance of the stm will be limited to the rate * of cleanup, and using a pool seriously improves scalability. * <p/> * Improvement: atm there is only one single type of tranlocal. If there are more types of tranlocals, * each class needs to have an index. This index can be used to determine the type of ref. If the pool * contains an array of arrays, where the first array is index based on the type of the ref, finding the * second array (that contains pooled tranlocals) can be found easily. * <p/> * ObjectPool is not thread safe and should not be shared between threads. * <p/> * This class is generated. * * @author Peter Veentjer */ @SuppressWarnings({"ClassWithTooManyFields"}) public final class GammaObjectPool { private final static boolean ENABLED = Boolean.parseBoolean( System.getProperty("org.multiverse.stm,gamma.GammaObjectPool.enabled", "true")); private final static boolean TRANLOCAL_POOLING_ENABLED = Boolean.parseBoolean( System.getProperty("org.multiverse.stm.gamma.GammaObjectPool.tranlocalPooling", String.valueOf(ENABLED))); private final static boolean TRANLOCALARRAY_POOLING_ENABLED = Boolean.parseBoolean( System.getProperty("org.multiverse.stm.gamma.GammaObjectPool.tranlocalArrayPooling", String.valueOf(ENABLED))); private final static boolean LISTENER_POOLING_ENABLED = Boolean.parseBoolean( System.getProperty("org.multiverse.stm.gamma.GammaObjectPool.listenersPooling", String.valueOf(ENABLED))); private final static boolean LISTENERSARRAY_POOLING_ENABLED = Boolean.parseBoolean( System.getProperty("org.multiverse.stm.gamma.GammaObjectPool.listenersArrayPooling", String.valueOf(ENABLED))); private final static boolean ARRAYLIST_POOLING_ENABLED = Boolean.parseBoolean( System.getProperty("org.multiverse.stm.gamma.GammaObjectPool.arrayListPooling", String.valueOf(ENABLED))); private final static boolean CALLABLENODE_POOLING_ENABLED = Boolean.parseBoolean( System.getProperty("org.multiverse.stm.gamma.GammaObjectPool.callableNodePooling", String.valueOf(ENABLED))); private final boolean tranlocalPoolingEnabled; private final boolean tranlocalArrayPoolingEnabled; private final boolean listenersPoolingEnabled; private final boolean listenersArrayPoolingEnabled; private final boolean arrayListPoolingEnabled; private final boolean callableNodePoolingEnabled; private final Tranlocal[] tranlocals = new Tranlocal[100]; private int lastUsedGammaTxnRef = -1; private final Listeners[] listenersPool = new Listeners[100]; private int listenersPoolIndex = -1; private final ArrayList[] arrayListPool = new ArrayList[10]; private int arrayListPoolIndex = -1; private final CallableNode[] callableNodePool = new CallableNode[100]; private int callableNodePoolIndex = -1; public GammaObjectPool() { arrayListPoolingEnabled = ARRAYLIST_POOLING_ENABLED; tranlocalArrayPoolingEnabled = TRANLOCALARRAY_POOLING_ENABLED; tranlocalPoolingEnabled = TRANLOCAL_POOLING_ENABLED; listenersPoolingEnabled = LISTENER_POOLING_ENABLED; listenersArrayPoolingEnabled = LISTENERSARRAY_POOLING_ENABLED; callableNodePoolingEnabled = CALLABLENODE_POOLING_ENABLED; } /** * Takes a Tranlocal from the pool for the specified GammaTxnRef. * * @param owner the GammaTxnRef to get the Tranlocal for. * @return the pooled tranlocal, or null if none is found. * @throws NullPointerException if owner is null. */ public Tranlocal take(final BaseGammaTxnRef owner) { if (owner == null) { throw new NullPointerException(); } if (lastUsedGammaTxnRef == -1) { Tranlocal tranlocal = new Tranlocal(); tranlocal.owner = owner; return tranlocal; } Tranlocal tranlocal = tranlocals[lastUsedGammaTxnRef]; tranlocal.owner = owner; tranlocals[lastUsedGammaTxnRef] = null; lastUsedGammaTxnRef--; return tranlocal; } /** * Puts an old Tranlocal in this pool. If the tranlocal is allowed to be null, * the call is ignored. The same goes for when the tranlocal is permanent, since you * can't now how many transactions are still using it. * * @param tranlocal the Tranlocal to pool. */ public void put(final Tranlocal tranlocal) { if (!tranlocalPoolingEnabled) { return; } if (lastUsedGammaTxnRef == tranlocals.length - 1) { return; } lastUsedGammaTxnRef++; tranlocals[lastUsedGammaTxnRef] = tranlocal; } private Tranlocal[][] tranlocalArrayPool = new Tranlocal[8193][]; /** * Puts a GammaTranlocal array in the pool. * * @param array the GammaTranlocal array to put in the pool. * @throws NullPointerException is array is null. */ public void putTranlocalArray(final Tranlocal[] array) { if (array == null) { throw new NullPointerException(); } if (!tranlocalArrayPoolingEnabled) { return; } if (array.length - 1 > tranlocalArrayPool.length) { return; } int index = array.length; if (tranlocalArrayPool[index] != null) { return; } //lets clean the array for (int k = 0; k < array.length; k++) { array[k] = null; } tranlocalArrayPool[index] = array; } /** * Takes a tranlocal array from the pool with the given size. * * @param size the size of the array to take * @return the GammaTranlocal array taken from the pool, or null if none available. * @throws IllegalArgumentException if size smaller than 0. */ public Tranlocal[] takeTranlocalArray(final int size) { if (size < 0) { throw new IllegalArgumentException(); } if (!tranlocalArrayPoolingEnabled) { return new Tranlocal[size]; } if (size >= tranlocalArrayPool.length) { return new Tranlocal[size]; } if (tranlocalArrayPool[size] == null) { return new Tranlocal[size]; } Tranlocal[] array = tranlocalArrayPool[size]; tranlocalArrayPool[size] = null; return array; } /** * Takes a CallableNode from the pool, or null if none is available. * * @return the CallableNode from the pool, or null if none available. */ public CallableNode takeCallableNode() { if (!callableNodePoolingEnabled || callableNodePoolIndex == -1) { return new CallableNode(); } CallableNode node = callableNodePool[callableNodePoolIndex]; callableNodePool[callableNodePoolIndex] = null; callableNodePoolIndex--; return node; } /** * Puts a CallableNode in the pool. * * @param node the CallableNode to pool. * @throws NullPointerException if node is null. */ public void putCallableNode(CallableNode node) { if (node == null) { throw new NullPointerException(); } if (!callableNodePoolingEnabled || callableNodePoolIndex == callableNodePool.length - 1) { return; } node.prepareForPooling(); callableNodePoolIndex++; callableNodePool[callableNodePoolIndex] = node; } // ====================== array list =================================== /** * Takes an ArrayList from the pool, The returned ArrayList is cleared. * * @return the ArrayList from the pool, or null of none is found. */ public ArrayList takeArrayList() { if (!arrayListPoolingEnabled || arrayListPoolIndex == -1) { return new ArrayList(10); } ArrayList list = arrayListPool[arrayListPoolIndex]; arrayListPool[arrayListPoolIndex] = null; arrayListPoolIndex--; return list; } /** * Puts an ArrayList in this pool. The ArrayList will be cleared before being placed * in the pool. * * @param list the ArrayList to place in the pool. * @throws NullPointerException if list is null. */ public void putArrayList(ArrayList list) { if (list == null) { throw new NullPointerException(); } if (!arrayListPoolingEnabled || arrayListPoolIndex == arrayListPool.length - 1) { return; } list.clear(); arrayListPoolIndex++; arrayListPool[arrayListPoolIndex] = list; } // ============================ listeners ================================== /** * Takes a Listeners object from the pool. * * @return the Listeners object taken from the pool. or null if none is taken. */ public Listeners takeListeners() { if (!listenersPoolingEnabled || listenersPoolIndex == -1) { return new Listeners(); } Listeners listeners = listenersPool[listenersPoolIndex]; listenersPool[listenersPoolIndex] = null; listenersPoolIndex--; return listeners; } /** * Puts a Listeners object in the pool. The Listeners object is preparedForPooling before * it is put in the pool. The next Listeners object is ignored (the next field itself is ignored). * * @param listeners the Listeners object to pool. * @throws NullPointerException is listeners is null. */ public void putListeners(Listeners listeners) { if (listeners == null) { throw new NullPointerException(); } if (!listenersPoolingEnabled || listenersPoolIndex == listenersPool.length - 1) { return; } listeners.prepareForPooling(); listenersPoolIndex++; listenersPool[listenersPoolIndex] = listeners; } // ============================= listeners array ============================= private Listeners[] listenersArray = new Listeners[100000]; /** * Takes a Listeners array from the pool. If an array is returned, it is completely nulled. * * @param minimalSize the minimalSize of the Listeners array. * @return the found Listeners array, or null if none is taken from the pool. * @throws IllegalArgumentException if minimalSize is smaller than 0. */ public Listeners[] takeListenersArray(int minimalSize) { if (minimalSize < 0) { throw new IllegalArgumentException(); } if (!listenersArrayPoolingEnabled) { return new Listeners[minimalSize]; } if (listenersArray == null || listenersArray.length < minimalSize) { return new Listeners[minimalSize]; } Listeners[] result = listenersArray; listenersArray = null; return result; } /** * Puts a Listeners array in the pool. * <p/> * Listeners array should be nulled before being put in the pool. It is not going to be done by this * GammaObjectPool but should be done when the listeners on the listeners array are notified. * * @param listenersArray the array to pool. * @throws NullPointerException if listenersArray is null. */ public void putListenersArray(Listeners[] listenersArray) { if (listenersArray == null) { throw new NullPointerException(); } if (!listenersArrayPoolingEnabled) { return; } if (this.listenersArray != listenersArray) { return; } this.listenersArray = listenersArray; } }