1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jdo.util;
18
19 import java.util.Stack;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23
24 /***
25 * A general purpose pooling class.
26 *
27 * @author Dave Bristor
28 */
29 public class Pool {
30
31 private final Stack stack = new Stack();
32
33
34 private final int size;
35
36
37 private int count = 0;
38
39 /*** Number of millis to wait for a free entry
40 * Currently fixed; might be made configurable in future.
41 */
42 private int waitMillis = 1000;
43
44 /*** Number of times to wait for a free entry
45 * Currently fixed; might be made configurable in future.
46 */
47 private int waitNumber = 5;
48
49 /*** I18N */
50 private final static I18NHelper msg = I18NHelper.getInstance("org.apache.jdo.util.Bundle");
51
52
53 static final Log test = LogFactory.getFactory().getInstance(
54 "org.apache.jdo.util");
55
56 /***
57 * Constructs a pool that will limit the number of objects which it can
58 * contain.
59 * @param size The maximum number of items that can be put into the pool.
60 */
61 public Pool(int size) {
62 this.size = size;
63 }
64
65 /***
66 * Puts the given object into the pool, if there the pool has fewer than
67 * the number of elements specifed when created. If the pool is full,
68 * blocks until an element is removed.
69 * @param o Object to be put in the pool.
70 * @throws InterruptedException
71 */
72 public synchronized void put(Object o) throws InterruptedException {
73 boolean debug = test.isDebugEnabled();
74
75 if (debug) {
76 test.debug("Pool.put: " + o);
77 }
78
79 if (count > size || count < 0) {
80 if (debug) {
81 test.debug("Pool: count " + count +
82 " out of range 0-" + size);
83 }
84 throw new RuntimeException(
85 msg.msg(
86 "EXC_CountOutOfRange",
87 new Integer(count).toString(),
88 new Integer(size).toString()));
89 }
90
91 if (stack.contains(o)) {
92 if (debug) {
93 test.debug("Pool: duplicate object");
94 }
95 throw new RuntimeException(
96 msg.msg(
97 "EXC_DuplicateObject", o));
98 }
99
100 while (count == size) {
101 if (debug) {
102 test.debug("Pool.put: block");
103 }
104 wait();
105 }
106 stack.push(o);
107 ++count;
108 notify();
109 }
110
111 /***
112 * Gets an object from the pool, if one is available. If an object is not
113 * available, waits until one is. The waiting is governed by two
114 * variables, which are currently fixed: waitMillis and waitNumber.
115 * If no object is available from the pool within (waitNumber) times
116 * (waitMillis) milliseconds, then a RuntimeException is thrown.
117 * In future, the waitMillis and waitNumber should be configurable.
118 * @return An object from the pool.
119 */
120 public synchronized Object get() throws InterruptedException {
121 boolean debug = test.isDebugEnabled();
122 Object rc = null;
123
124 if (count > size || count < 0) {
125 if (debug) {
126 test.debug("Pool: count " + count +
127 " out of range 0-" + size);
128 }
129 throw new RuntimeException(
130 msg.msg(
131 "EXC_CountOutOfRange",
132 new Integer(count).toString(),
133 new Integer(size).toString()));
134 }
135
136 int timeouts = 0;
137 while (count == 0 && timeouts++ < waitNumber) {
138 if (debug) {
139 test.debug("Pool.get: block " + timeouts);
140 }
141 wait(waitMillis);
142 }
143 if (timeouts >= waitNumber) {
144 throw new RuntimeException(
145 msg.msg("EXC_PoolGetTimeout"));
146 }
147 rc = stack.pop();
148 --count;
149 notify();
150 if (debug) {
151 test.debug("Pool.get: " + rc);
152 }
153 return rc;
154 }
155 }