KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > protomatter > pool > SimpleObjectPool


1 package com.protomatter.pool;
2
3 /**
4  * {{{ The Protomatter Software License, Version 1.0
5  * derived from The Apache Software License, Version 1.1
6  *
7  * Copyright (c) 1998-2002 Nate Sammons. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed for the
24  * Protomatter Software Project
25  * (http://protomatter.sourceforge.net/)."
26  * Alternately, this acknowledgment may appear in the software itself,
27  * if and wherever such third-party acknowledgments normally appear.
28  *
29  * 4. The names "Protomatter" and "Protomatter Software Project" must
30  * not be used to endorse or promote products derived from this
31  * software without prior written permission. For written
32  * permission, please contact support@protomatter.com.
33  *
34  * 5. Products derived from this software may not be called "Protomatter",
35  * nor may "Protomatter" appear in their name, without prior written
36  * permission of the Protomatter Software Project
37  * (support@protomatter.com).
38  *
39  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
40  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42  * DISCLAIMED. IN NO EVENT SHALL THE PROTOMATTER SOFTWARE PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
46  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE. }}}
51  */

52
53 import java.util.*;
54 import com.protomatter.util.*;
55 import com.protomatter.syslog.Syslog;
56
57 /**
58  * A minimal implementation of an ObjectPool.
59  * This class provides a non-growing pool that
60  * sleeps the threads that are trying to check
61  * something out of the pool, and wakes them
62  * up in-order when something is checked back in.
63  *
64  * @see ObjectPool
65  */

66 public abstract class SimpleObjectPool
67 implements ObjectPool
68 {
69   /**
70    * An object used for synchronization.
71    */

72   protected Object JavaDoc sync = new Object JavaDoc();
73
74   private List waiters = new ArrayList();
75   private List checkedOutObjects = new ArrayList();
76   private boolean monitorCheckedOutObjects = true;
77
78   /**
79    * Initialize the object pool. Checked out
80    * objects will be monitored.
81    */

82   public SimpleObjectPool()
83   {
84     this(true);
85   }
86
87   /**
88    * Initialize the object pool. Checked out
89    * objects will be monitored if <TT>monitorCheckedOutObjects</TT>
90    * is true.
91    */

92   public SimpleObjectPool(boolean monitorCheckedOutObjects)
93   {
94     super();
95     this.monitorCheckedOutObjects = monitorCheckedOutObjects;
96   }
97
98   /**
99    * Get a reference to the object being used
100    * as a synchronization lock. Subclasses that
101    * need to lock the operation of the pool while
102    * they perform maintenance should synchronize
103    * on this object and then manipulate the pool.
104    */

105   protected Object JavaDoc getSyncObject()
106   {
107     return this.sync;
108   }
109
110   /**
111    * Get the number of threads waiting for an object to become available.
112    */

113   public int getNumWaiters()
114   {
115     return this.waiters.size();
116   }
117
118   /**
119    * Get the number of objects that are currently checked out.
120    */

121   public int getObjectsInUse()
122   {
123     return this.checkedOutObjects.size();
124   }
125
126   /**
127    * Add a thread to the queue of threads waiting for the shared object.
128    * If, for some reason, the thread is already in the queue, then this
129    * call will be ignored --- the thread can only be in the queue once
130    * via this method.
131    */

132   private final void addToWaiters(Thread JavaDoc t)
133   {
134     synchronized (waiters)
135     {
136       if (!waiters.contains(t))
137       {
138         waiters.add(t);
139         //Syslog.debug(this, "Adding waiter " + t);
140
}
141     }
142   }
143
144   /**
145    * Remove the given thread from the list of waiters. This
146    * method should only be called if you know what you're
147    * doing.
148    */

149   public final void removeWaiter(Thread JavaDoc t)
150   {
151     synchronized (waiters)
152     {
153       waiters.remove(t);
154     }
155   }
156
157   /**
158    * Get the next thread in line and remove it from the waiters.
159    */

160   private final Thread JavaDoc getNextWaiter()
161   {
162     synchronized (waiters)
163     {
164       if (waiters.size() != 0)
165         return (Thread JavaDoc)waiters.remove(0);
166       return null;
167     }
168   }
169
170   /**
171    * Implements a first in, first out reservation scheme. If no
172    * threads are waiting for the object, then the caller never blocks.
173    * If there are waiters, then the caller "get's in line," and waits
174    * for their turn with the object.
175    *
176    * @exception Exception If there is a problem checking an object out of the pool.
177    */

178   public ObjectPoolObject checkout()
179   throws Exception JavaDoc
180   {
181     Thread JavaDoc thread = Thread.currentThread();
182
183     ObjectPoolObject obj = null;
184     while (true) // mmmm.... infinity
185
{
186       synchronized (sync)
187       {
188         boolean done = false;
189
190         while (!done)
191         {
192           obj = getNextPoolObject(); // can throw exception
193

194           if (obj != null)
195           {
196             obj.beforeObjectPoolObjectCheckout();
197             // make sure the checked out object is still valid.
198
if (obj.isObjectPoolObjectValid())
199             {
200               if (monitorCheckedOutObjects)
201                 checkedOutObjects.add(obj);
202               return obj;
203             }
204             else
205             {
206               obj.deleteObjectPoolObject();
207             }
208           }
209           else
210           {
211             done = true;
212           }
213         }
214       }
215
216       // if we got here it's because we didn't get
217
// anything from the pool. We'll just wait
218
// till someone wakes us up and give it another
219
// try.
220
synchronized (thread)
221       {
222         addToWaiters(thread);
223         thread.wait();
224       }
225     }
226   }
227
228   /**
229    * Check an object back into the pool. If there are
230    * threads in the wait queue, the thread that has been waiting
231    * longest will get the shared object next. The waiter may not receive
232    * the shared object immediately, however.
233    *
234    * @exception Exception If there was a problem checking in the object.
235    */

236   public void checkin(ObjectPoolObject opo)
237   throws Exception JavaDoc
238   {
239     opo.afterObjectPoolObjectCheckin();
240     synchronized(sync)
241     {
242       try
243       {
244         if (opo.isObjectPoolObjectValid())
245           checkinPoolObject(opo); // can throw Exception
246
else
247           opo.deleteObjectPoolObject();
248       }
249       finally
250       {
251         // make sure to remove it from the list of
252
// checked out objects.
253
if (monitorCheckedOutObjects)
254           this.checkedOutObjects.remove(opo);
255
256         // wake up the next guy in line.
257
Thread JavaDoc waiter = getNextWaiter();
258         if (waiter != null)
259         {
260           synchronized (waiter)
261           {
262             waiter.notify();
263           }
264         }
265       }
266     }
267   }
268
269   /**
270    * Get the list of objects that are currently checked out of the pool.
271    */

272   protected List getCheckedOutObjects()
273   {
274     return this.checkedOutObjects;
275   }
276
277   /**
278    * This method needs to be implemented by sub-classes.
279    * It should return the next element in the pool, or
280    * null if the pool is empty. Growable implementations
281    * should use this method to add more elements to the
282    * pool.
283    *
284    * @exception Exception If there is a problem getting the
285    * next object for the pool -- this is implementation specific.
286    */

287   protected abstract ObjectPoolObject getNextPoolObject()
288   throws Exception JavaDoc;
289
290   /**
291    * This method needs to be implemented by sub-classes.
292    * It should add the given ObjectPoolObject to the pool.
293    *
294    * @exception Exception If there is a problem checking in the
295    * object -- this is implementation specific.
296    */

297   protected abstract void checkinPoolObject(ObjectPoolObject o)
298   throws Exception JavaDoc;
299
300   /**
301    * To be implemented by sub-classes. This is a factory
302    * method for creating objects that go in this pool.
303    *
304    * @exception Exception If there is a problem creating the next
305    * object for the pool -- this is implementation specific.
306    */

307   protected abstract ObjectPoolObject createObjectPoolObject()
308   throws Exception JavaDoc;
309 }
310
Popular Tags