* @param <T>\r
*/\r
public class Pool<T> {\r
- /**\r
- * This is a constant which specified the default maximum number of unused\r
- * objects to be held at any given time.\r
- */\r
- private static final int MAX_RANGE = 6; // safety\r
+ /**\r
+ * This is a constant which specified the default maximum number of unused\r
+ * objects to be held at any given time.\r
+ */\r
+ private static final int MAX_RANGE = 6; // safety\r
\r
- /**\r
- * only Simple List needed.\r
- * \r
- * NOTE TO MAINTAINERS: THIS OBJECT DOES IT'S OWN SYNCHRONIZATION. All\r
- * changes that touch list must account for correctly synchronizing list.\r
- */\r
- private LinkedList<Pooled<T>> list;\r
+ /**\r
+ * only Simple List needed.\r
+ * \r
+ * NOTE TO MAINTAINERS: THIS OBJECT DOES IT'S OWN SYNCHRONIZATION. All\r
+ * changes that touch list must account for correctly synchronizing list.\r
+ */\r
+ private LinkedList<Pooled<T>> list;\r
\r
- /**\r
- * keep track of how many elements exist, to avoid asking list.\r
- */\r
- private int count;\r
+ /**\r
+ * keep track of how many elements exist, to avoid asking list.\r
+ */\r
+ private int count;\r
\r
- /**\r
- * Spares are those Object that are primed and ready to go.\r
- */\r
- private int spares;\r
+ /**\r
+ * Spares are those Object that are primed and ready to go.\r
+ */\r
+ private int spares;\r
\r
- /**\r
- * Actual MAX number of spares allowed to hang around. Can be set to\r
- * something besides the default MAX_RANGE.\r
- */\r
- private int max_range = MAX_RANGE;\r
+ /**\r
+ * Actual MAX number of spares allowed to hang around. Can be set to\r
+ * something besides the default MAX_RANGE.\r
+ */\r
+ private int max_range = MAX_RANGE;\r
\r
- /**\r
- * The Creator for this particular pool. It must work for type T.\r
- */\r
- private Creator<T> creator;\r
+ /**\r
+ * The Creator for this particular pool. It must work for type T.\r
+ */\r
+ private Creator<T> creator;\r
\r
- /**\r
- * Create a new Pool, given the implementation of Creator<T>, which must be\r
- * able to create/destroy T objects at will.\r
- * \r
- * @param creator\r
- */\r
- public Pool(Creator<T> creator) {\r
- count = spares = 0;\r
- this.creator = creator;\r
- list = new LinkedList<Pooled<T>>();\r
- }\r
+ /**\r
+ * Create a new Pool, given the implementation of Creator<T>, which must be\r
+ * able to create/destroy T objects at will.\r
+ * \r
+ * @param creator\r
+ */\r
+ public Pool(Creator<T> creator) {\r
+ count = spares = 0;\r
+ this.creator = creator;\r
+ list = new LinkedList<>();\r
+ }\r
\r
- /**\r
- * Preallocate a certain number of T Objects. Useful for services so that\r
- * the first transactions don't get hit with all the Object creation costs\r
- * \r
- * @param lt\r
- * @param prime\r
- * @throws APIException\r
- */\r
- public void prime(LogTarget lt, int prime) throws APIException {\r
- for (int i = 0; i < prime; ++i) {\r
- Pooled<T> pt = new Pooled<T>(creator.create(), this, lt);\r
- synchronized (list) {\r
- list.addFirst(pt);\r
- ++count;\r
- }\r
- }\r
+ /**\r
+ * Preallocate a certain number of T Objects. Useful for services so that\r
+ * the first transactions don't get hit with all the Object creation costs\r
+ * \r
+ * @param lt\r
+ * @param prime\r
+ * @throws APIException\r
+ */\r
+ public void prime(LogTarget lt, int prime) throws APIException {\r
+ for (int i = 0; i < prime; ++i) {\r
+ Pooled<T> pt = new Pooled<T>(creator.create(), this, lt);\r
+ synchronized (list) {\r
+ list.addFirst(pt);\r
+ ++count;\r
+ }\r
+ }\r
\r
- }\r
+ }\r
\r
- /**\r
- * Destroy and remove all remaining objects. This is valuable for closing\r
- * down all Allocated objects cleanly for exiting. It is also a good method\r
- * for removing objects when, for instance, all Objects are invalid because\r
- * of broken connections, etc.\r
- */\r
- public void drain() {\r
- synchronized (list) {\r
- for (int i = 0; i < list.size(); ++i) {\r
- Pooled<T> pt = list.remove();\r
- creator.destroy(pt.content);\r
- pt.logTarget.log("Pool drained ", creator.toString());\r
- }\r
- count = spares = 0;\r
- }\r
+ /**\r
+ * Destroy and remove all remaining objects. This is valuable for closing\r
+ * down all Allocated objects cleanly for exiting. It is also a good method\r
+ * for removing objects when, for instance, all Objects are invalid because\r
+ * of broken connections, etc.\r
+ */\r
+ public void drain() {\r
+ synchronized (list) {\r
+ for (int i = 0; i < list.size(); ++i) {\r
+ Pooled<T> pt = list.remove();\r
+ creator.destroy(pt.content);\r
+ pt.logTarget.log("Pool drained ", creator.toString());\r
+ }\r
+ count = spares = 0;\r
+ }\r
\r
- }\r
+ }\r
\r
- /**\r
- * This is the essential function for Pool. Get an Object "T" inside a\r
- * "Pooled<T>" object. If there is a spare Object, then use it. If not, then\r
- * create and pass back.\r
- * \r
- * This one uses a Null LogTarget\r
- * \r
- * IMPORTANT: When the use of this object is done (and the object is still\r
- * in a valid state), then "done()" should be called immediately to allow\r
- * the object to be reused. That is the point of the Pool...\r
- * \r
- * If the Object is in an invalid state, then "toss()" should be used so the\r
- * Pool doesn't pass on invalid objects to others.\r
- * \r
- * @param lt\r
- * @return\r
- * @throws APIException\r
- */\r
- public Pooled<T> get() throws APIException {\r
- Pooled<T> pt;\r
- synchronized (list) {\r
- if (list.isEmpty()) {\r
- pt = null;\r
- } else {\r
- pt = list.removeLast();\r
- --count;\r
- creator.reuse(pt.content);\r
- }\r
- }\r
- if (pt == null) {\r
- if (spares < max_range)\r
- ++spares;\r
- pt = new Pooled<T>(creator.create(), this, LogTarget.NULL);\r
- } else {\r
- if (spares > 1)\r
- --spares;\r
- }\r
- return pt;\r
- }\r
+ /**\r
+ * This is the essential function for Pool. Get an Object "T" inside a\r
+ * "Pooled<T>" object. If there is a spare Object, then use it. If not, then\r
+ * create and pass back.\r
+ * \r
+ * This one uses a Null LogTarget\r
+ * \r
+ * IMPORTANT: When the use of this object is done (and the object is still\r
+ * in a valid state), then "done()" should be called immediately to allow\r
+ * the object to be reused. That is the point of the Pool...\r
+ * \r
+ * If the Object is in an invalid state, then "toss()" should be used so the\r
+ * Pool doesn't pass on invalid objects to others.\r
+ * \r
+ * @param lt\r
+ * @return\r
+ * @throws APIException\r
+ */\r
+ public Pooled<T> get() throws APIException {\r
+ Pooled<T> pt;\r
+ synchronized (list) {\r
+ if (list.isEmpty()) {\r
+ pt = null;\r
+ } else {\r
+ pt = list.removeLast();\r
+ --count;\r
+ creator.reuse(pt.content);\r
+ }\r
+ }\r
+ if (pt == null) {\r
+ if (spares < max_range)\r
+ ++spares;\r
+ pt = new Pooled<T>(creator.create(), this, LogTarget.NULL);\r
+ } else {\r
+ if (spares > 1)\r
+ --spares;\r
+ }\r
+ return pt;\r
+ }\r
\r
- /**\r
- * This is the essential function for Pool. Get an Object "T" inside a\r
- * "Pooled<T>" object. If there is a spare Object, then use it. If not, then\r
- * create and pass back.\r
- * \r
- * If you don't have access to a LogTarget from Env, use LogTarget.NULL\r
- * \r
- * IMPORTANT: When the use of this object is done (and the object is still\r
- * in a valid state), then "done()" should be called immediately to allow\r
- * the object to be reused. That is the point of the Pool...\r
- * \r
- * If the Object is in an invalid state, then "toss()" should be used so the\r
- * Pool doesn't pass on invalid objects to others.\r
- * \r
- * @param lt\r
- * @return\r
- * @throws APIException\r
- */\r
- public Pooled<T> get(LogTarget lt) throws APIException {\r
- Pooled<T> pt;\r
- synchronized (list) {\r
- if (list.isEmpty()) {\r
- pt = null;\r
- } else {\r
- pt = list.remove();\r
- --count;\r
- creator.reuse(pt.content);\r
- }\r
- }\r
- if (pt == null) {\r
- if (spares < max_range)\r
- ++spares;\r
- pt = new Pooled<T>(creator.create(), this, lt);\r
- lt.log("Pool created ", creator.toString());\r
- } else {\r
- if (spares > 1)\r
- --spares;\r
- }\r
- return pt;\r
- }\r
+ /**\r
+ * This is the essential function for Pool. Get an Object "T" inside a\r
+ * "Pooled<T>" object. If there is a spare Object, then use it. If not, then\r
+ * create and pass back.\r
+ * \r
+ * If you don't have access to a LogTarget from Env, use LogTarget.NULL\r
+ * \r
+ * IMPORTANT: When the use of this object is done (and the object is still\r
+ * in a valid state), then "done()" should be called immediately to allow\r
+ * the object to be reused. That is the point of the Pool...\r
+ * \r
+ * If the Object is in an invalid state, then "toss()" should be used so the\r
+ * Pool doesn't pass on invalid objects to others.\r
+ * \r
+ * @param lt\r
+ * @return\r
+ * @throws APIException\r
+ */\r
+ public Pooled<T> get(LogTarget lt) throws APIException {\r
+ Pooled<T> pt;\r
+ synchronized (list) {\r
+ if (list.isEmpty()) {\r
+ pt = null;\r
+ } else {\r
+ pt = list.remove();\r
+ --count;\r
+ creator.reuse(pt.content);\r
+ }\r
+ }\r
+ if (pt == null) {\r
+ if (spares < max_range)\r
+ ++spares;\r
+ pt = new Pooled<T>(creator.create(), this, lt);\r
+ lt.log("Pool created ", creator.toString());\r
+ } else {\r
+ if (spares > 1)\r
+ --spares;\r
+ }\r
+ return pt;\r
+ }\r
\r
- /**\r
- * This function will validate whether the Objects are still in a usable\r
- * state. If not, they are tossed from the Pool. This is valuable to have\r
- * when Remote Connections go down, and there is a question on whether the\r
- * Pooled Objects are still functional.\r
- * \r
- * @return\r
- */\r
- public boolean validate() {\r
- boolean rv = true;\r
- synchronized (list) {\r
- for (Pooled<T> t : list) {\r
- if (!creator.isValid(t.content)) {\r
- rv = false;\r
- t.toss();\r
- list.remove(t);\r
- }\r
- }\r
- }\r
- return rv;\r
- }\r
+ /**\r
+ * This function will validate whether the Objects are still in a usable\r
+ * state. If not, they are tossed from the Pool. This is valuable to have\r
+ * when Remote Connections go down, and there is a question on whether the\r
+ * Pooled Objects are still functional.\r
+ * \r
+ * @return\r
+ */\r
+ public boolean validate() {\r
+ boolean rv = true;\r
+ synchronized (list) {\r
+ for (Pooled<T> t : list) {\r
+ if (!creator.isValid(t.content)) {\r
+ rv = false;\r
+ t.toss();\r
+ list.remove(t);\r
+ }\r
+ }\r
+ }\r
+ return rv;\r
+ }\r
\r
- /**\r
- * This is an internal method, used only by the Internal Pooled<T> class.\r
- * \r
- * The Pooled<T> class "offers" it's Object back after use. It is an\r
- * "offer", because Pool will simply destroy and remove the object if it has\r
- * more than enough spares.\r
- * \r
- * @param lt\r
- * @param used\r
- * @return\r
- */\r
- // Used only by Pooled<T>\r
- private boolean offer(LogTarget lt, Pooled<T> used) {\r
- if (count < spares) {\r
- synchronized (list) {\r
- list.addFirst(used);\r
- ++count;\r
- }\r
- lt.log("Pool recovered ", creator.toString());\r
- } else {\r
- lt.log("Pool destroyed ", creator.toString());\r
- creator.destroy(used.content);\r
- }\r
- return false;\r
- }\r
+ /**\r
+ * This is an internal method, used only by the Internal Pooled<T> class.\r
+ * \r
+ * The Pooled<T> class "offers" it's Object back after use. It is an\r
+ * "offer", because Pool will simply destroy and remove the object if it has\r
+ * more than enough spares.\r
+ * \r
+ * @param lt\r
+ * @param used\r
+ * @return\r
+ */\r
+ // Used only by Pooled<T>\r
+ private boolean offer(LogTarget lt, Pooled<T> used) {\r
+ if (count < spares) {\r
+ synchronized (list) {\r
+ list.addFirst(used);\r
+ ++count;\r
+ }\r
+ lt.log("Pool recovered ", creator.toString());\r
+ } else {\r
+ lt.log("Pool destroyed ", creator.toString());\r
+ creator.destroy(used.content);\r
+ }\r
+ return false;\r
+ }\r
\r
- /**\r
- * The Creator Interface give the Pool the ability to Create, Destroy and\r
- * Validate the Objects it is maintaining. Thus, it is a specially written\r
- * Implementation for each type.\r
- * \r
- * @author Jonathan\r
- * \r
- * @param <T>\r
- */\r
- public interface Creator<T> {\r
- public T create() throws APIException;\r
+ /**\r
+ * The Creator Interface give the Pool the ability to Create, Destroy and\r
+ * Validate the Objects it is maintaining. Thus, it is a specially written\r
+ * Implementation for each type.\r
+ * \r
+ * @author Jonathan\r
+ * \r
+ * @param <T>\r
+ */\r
+ public interface Creator<T> {\r
+ public T create() throws APIException;\r
\r
- public void destroy(T t);\r
+ public void destroy(T t);\r
\r
- public boolean isValid(T t);\r
+ public boolean isValid(T t);\r
\r
- public void reuse(T t);\r
- }\r
+ public void reuse(T t);\r
+ }\r
\r
- /**\r
- * The "Pooled<T>" class is the transient class that wraps the actual Object\r
- * T for API use/ It gives the ability to return ("done()", or "toss()") the\r
- * Object to the Pool when processing is finished.\r
- * \r
- * For Safety, i.e. to avoid memory leaks and invalid Object States, there\r
- * is a "finalize" method. It is strictly for when coder forgets to return\r
- * the object, or perhaps hasn't covered the case during Exceptions or\r
- * Runtime Exceptions with finally (preferred). This should not be\r
- * considered normal procedure, as finalize() is called at an undetermined\r
- * time during garbage collection, and is thus rather useless for a Pool.\r
- * However, we don't want Coding Mistakes to put the whole program in an\r
- * invalid state, so if something happened such that "done()" or "toss()"\r
- * were not called, the resource is still cleaned up as well as possible.\r
- * \r
- * @author Jonathan\r
- * \r
- * @param <T>\r
- */\r
- public static class Pooled<T> {\r
- public final T content;\r
- private Pool<T> pool;\r
- protected LogTarget logTarget;\r
+ /**\r
+ * The "Pooled<T>" class is the transient class that wraps the actual Object\r
+ * T for API use/ It gives the ability to return ("done()", or "toss()") the\r
+ * Object to the Pool when processing is finished.\r
+ * \r
+ * For Safety, i.e. to avoid memory leaks and invalid Object States, there\r
+ * is a "finalize" method. It is strictly for when coder forgets to return\r
+ * the object, or perhaps hasn't covered the case during Exceptions or\r
+ * Runtime Exceptions with finally (preferred). This should not be\r
+ * considered normal procedure, as finalize() is called at an undetermined\r
+ * time during garbage collection, and is thus rather useless for a Pool.\r
+ * However, we don't want Coding Mistakes to put the whole program in an\r
+ * invalid state, so if something happened such that "done()" or "toss()"\r
+ * were not called, the resource is still cleaned up as well as possible.\r
+ * \r
+ * @author Jonathan\r
+ * \r
+ * @param <T>\r
+ */\r
+ public static class Pooled<T> {\r
+ public final T content;\r
+ private Pool<T> pool;\r
+ protected LogTarget logTarget;\r
\r
- /**\r
- * Create the Wrapping Object Pooled<T>.\r
- * \r
- * @param t\r
- * @param pool\r
- * @param logTarget\r
- */\r
- public Pooled(T t, Pool<T> pool, LogTarget logTarget) {\r
- content = t;\r
- this.pool = pool;\r
- this.logTarget = logTarget;\r
- }\r
+ /**\r
+ * Create the Wrapping Object Pooled<T>.\r
+ * \r
+ * @param t\r
+ * @param pool\r
+ * @param logTarget\r
+ */\r
+ public Pooled(T t, Pool<T> pool, LogTarget logTarget) {\r
+ content = t;\r
+ this.pool = pool;\r
+ this.logTarget = logTarget;\r
+ }\r
\r
- /**\r
- * This is the key API for the Pool, as calling "done()" offers this\r
- * object back to the Pool for reuse.\r
- * \r
- * Do not use the Pooled<T> object again after calling "done()".\r
- */\r
- public void done() {\r
- if (pool != null) {\r
- pool.offer(logTarget, this);\r
- }\r
- }\r
+ /**\r
+ * This is the key API for the Pool, as calling "done()" offers this\r
+ * object back to the Pool for reuse.\r
+ * \r
+ * Do not use the Pooled<T> object again after calling "done()".\r
+ */\r
+ public void done() {\r
+ if (pool != null) {\r
+ pool.offer(logTarget, this);\r
+ }\r
+ }\r
\r
- /**\r
- * The user of the Object may discover that the Object t is no longer in\r
- * a valid state. Don't put Garbage back in the Refrigerator... Toss it,\r
- * if it's no longer valid.\r
- * \r
- * toss() is also used for draining the Pool, etc.\r
- * \r
- * toss() will attempt to destroy the Object by using the Creator\r
- * Interface.\r
- * \r
- */\r
- public void toss() {\r
- if (pool != null) {\r
- pool.creator.destroy(content);\r
- }\r
- // Don't allow finalize to put it back in.\r
- pool = null;\r
- }\r
+ /**\r
+ * The user of the Object may discover that the Object t is no longer in\r
+ * a valid state. Don't put Garbage back in the Refrigerator... Toss it,\r
+ * if it's no longer valid.\r
+ * \r
+ * toss() is also used for draining the Pool, etc.\r
+ * \r
+ * toss() will attempt to destroy the Object by using the Creator\r
+ * Interface.\r
+ * \r
+ */\r
+ public void toss() {\r
+ if (pool != null) {\r
+ pool.creator.destroy(content);\r
+ }\r
+ // Don't allow finalize to put it back in.\r
+ pool = null;\r
+ }\r
\r
- /**\r
- * Just in case someone neglected to offer back object... Do not rely on\r
- * this, as there is no specific time when finalize is called, which\r
- * rather defeats the purpose of a Pool.\r
- */\r
- @Override\r
- protected void finalize() throws Throwable {\r
- if (pool != null) {\r
- done();\r
- pool = null;\r
- }\r
- }\r
- }\r
+ /**\r
+ * Just in case someone neglected to offer back object... Do not rely on\r
+ * this, as there is no specific time when finalize is called, which\r
+ * rather defeats the purpose of a Pool.\r
+ */\r
+ @Override\r
+ protected void finalize() throws Throwable {\r
+ if (pool != null) {\r
+ done();\r
+ pool = null;\r
+ }\r
+ }\r
+ }\r
\r
- /**\r
- * Get the maximum number of spare objects allowed at any moment\r
- * \r
- * @return\r
- */\r
- public int getMaxRange() {\r
- return max_range;\r
- }\r
+ /**\r
+ * Get the maximum number of spare objects allowed at any moment\r
+ * \r
+ * @return\r
+ */\r
+ public int getMaxRange() {\r
+ return max_range;\r
+ }\r
\r
- /**\r
- * Set a Max Range for numbers of spare objects waiting to be used.\r
- * \r
- * No negative numbers are allowed\r
- * \r
- * @return\r
- */\r
- public void setMaxRange(int max_range) {\r
- // Do not allow negative numbers\r
- this.max_range = Math.max(0, max_range);\r
- }\r
+ /**\r
+ * Set a Max Range for numbers of spare objects waiting to be used.\r
+ * \r
+ * No negative numbers are allowed\r
+ * \r
+ * @return\r
+ */\r
+ public void setMaxRange(int max_range) {\r
+ // Do not allow negative numbers\r
+ this.max_range = Math.max(0, max_range);\r
+ }\r
\r
}\r