KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > util > Pool


1 // ========================================================================
2
// $Id: Pool.java,v 1.13 2005/08/13 00:01:28 gregwilkins Exp $
3
// Copyright 1999-2004 Mort Bay Consulting Pty. Ltd.
4
// ------------------------------------------------------------------------
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
// ========================================================================
15

16 package org.mortbay.util;
17
18 import java.io.Serializable JavaDoc;
19 import java.util.HashMap JavaDoc;
20
21 import org.apache.commons.logging.Log;
22 import org.mortbay.log.LogFactory;
23
24 /* ------------------------------------------------------------ */
25 /** A pool of Objects.
26  * <p>
27  * @version $Id: Pool.java,v 1.13 2005/08/13 00:01:28 gregwilkins Exp $
28  * @author Juancarlo Aņez <juancarlo@modelistica.com>
29  * @author Greg Wilkins <gregw@mortbay.com>
30  */

31 public class Pool
32     implements LifeCycle, Serializable JavaDoc
33 {
34     private static Log log = LogFactory.getLog(Pool.class);
35
36     /* ------------------------------------------------------------ */
37     static int __max =
38         Integer.getInteger("POOL_MAX",256).intValue();
39     static int __min =
40         Integer.getInteger("POOL_MIN",2).intValue();
41
42     
43     /* ------------------------------------------------------------ */
44     public static interface PondLife
45     {
46         int getID();
47         void enterPool(Pool pool,int id);
48         void poolClosing();
49         void leavePool();
50     }
51     
52     /* ------------------------------------------------------------------- */
53     static HashMap JavaDoc __nameMap=new HashMap JavaDoc();
54     
55     /* ------------------------------------------------------------------- */
56     private int _max = __max;
57     private int _min = __min;
58     private String JavaDoc _name;
59     private String JavaDoc _className;
60     private int _maxIdleTimeMs=10000;
61     private HashMap JavaDoc _attributes = new HashMap JavaDoc();
62     
63     private transient Class JavaDoc _class;
64     private transient PondLife[] _pondLife; // Array of pondlife indexed by ID.
65
private transient int[] _index; // Mapping of pondlife IDs. Entries with indexes <_available are idle IDs. Entries with indexes>_size are unused IDs.
66
private transient int _size;
67     private transient int _available;
68     private transient int _running=0;
69     private transient long _lastShrink=0; // control shrinking to once per maxIdleTime
70

71     /* ------------------------------------------------------------------- */
72     public static Pool getPool(String JavaDoc name)
73     {
74         return (Pool)__nameMap.get(name);
75     }
76
77     /* ------------------------------------------------------------------- */
78     /* Construct
79      */

80     public Pool()
81     {}
82
83     /* ------------------------------------------------------------ */
84     /**
85      * @return The name of the Pool.
86      */

87     public String JavaDoc getPoolName()
88     {
89         return _name;
90     }
91
92     /* ------------------------------------------------------------ */
93     /**
94      * @param name The pool name
95      * @exception IllegalStateException If the name is already defined.
96      */

97     public void setPoolName(String JavaDoc name)
98         throws IllegalStateException JavaDoc
99     {
100         synchronized(this)
101         {
102             synchronized(Pool.class)
103             {
104                 if (_name!=null && !_name.equals(name))
105                     __nameMap.remove(_name);
106                 if (__nameMap.containsKey(name))
107                     throw new IllegalStateException JavaDoc("Name already exists");
108                 _name=name;
109                 
110                 __nameMap.put(_name,this);
111             }
112         }
113     }
114     
115     /* ------------------------------------------------------------ */
116     /** Set the class.
117      * @param poolClass The class
118      * @exception IllegalStateException If the pool has already
119      * been started.
120      */

121     public void setPoolClass(Class JavaDoc poolClass)
122         throws IllegalStateException JavaDoc
123     {
124         synchronized(this)
125         {
126             if (_class!=poolClass)
127             {
128                 if (_running>0)
129                     throw new IllegalStateException JavaDoc("Thread Pool Running");
130                 if (!PondLife.class.isAssignableFrom(poolClass))
131                     throw new IllegalArgumentException JavaDoc("Not PondLife: "+poolClass);
132                 _class=poolClass;
133                 _className=_class.getName();
134             }
135         }
136     }
137     
138
139     /* ------------------------------------------------------------ */
140     public Class JavaDoc getPoolClass()
141     {
142         return _class;
143     }
144
145     /* ------------------------------------------------------------ */
146     public int getMinSize()
147     {
148         return _min;
149     }
150     
151     /* ------------------------------------------------------------ */
152     public void setMinSize(int min)
153     {
154         _min=min;
155     }
156     
157     /* ------------------------------------------------------------ */
158     public int getMaxSize()
159     {
160         return _max;
161     }
162     
163     /* ------------------------------------------------------------ */
164     public void setMaxSize(int max)
165     {
166         _max=max;
167     }
168     
169     /* ------------------------------------------------------------ */
170     public int getMaxIdleTimeMs()
171     {
172         return _maxIdleTimeMs;
173     }
174     
175     /* ------------------------------------------------------------ */
176     public void setMaxIdleTimeMs(int maxIdleTimeMs)
177     {
178         _maxIdleTimeMs=maxIdleTimeMs;
179     }
180     
181     /* ------------------------------------------------------------ */
182     public void setAttribute(String JavaDoc name,Object JavaDoc value)
183     {
184         _attributes.put(name,value);
185     }
186     
187     /* ------------------------------------------------------------ */
188     public Object JavaDoc getAttribute(String JavaDoc name)
189     {
190         return _attributes.get(name);
191     }
192     
193     /* ------------------------------------------------------------ */
194     public boolean isStarted()
195     {
196         return _running>0 && _pondLife!=null;
197     }
198     
199     /* ------------------------------------------------------------ */
200     public int size()
201     {
202         return _size;
203     }
204     
205     /* ------------------------------------------------------------ */
206     public int available()
207     {
208         return _available;
209     }
210     
211     
212     /* ------------------------------------------------------------ */
213     public void start()
214         throws Exception JavaDoc
215     {
216         synchronized(this)
217         {
218             _running++;
219             if (_running>1)
220                 return;
221
222             if (_min >= _max || _max<1)
223                 throw new IllegalStateException JavaDoc("!(0<=min<max)");
224
225             // Start the threads
226
_pondLife=new PondLife[_max];
227             _index=new int[_max];
228             _size=0;
229             _available=0;
230             
231             for (int i=0;i<_max;i++)
232                 _index[i]=i;
233             for (int i=0;i<_min;i++)
234                 newPondLife();
235         }
236     }
237
238     /* ------------------------------------------------------------ */
239     public void stop()
240         throws InterruptedException JavaDoc
241     {
242         synchronized(this)
243         {
244             _running--;
245             if (_running>0)
246                 return;
247             notifyAll();
248         }
249         
250         if (_pondLife!=null && _size>0)
251         {
252             for (int i=0;i<_pondLife.length;i++)
253                 closePondLife(i);
254             Thread.yield();
255             for (int i=0;i<_pondLife.length;i++)
256                 stopPondLife(i);
257         }
258
259         synchronized(this)
260         {
261             _pondLife=null;
262             _index=null;
263             _size=0;
264             _available=0;
265         }
266     }
267     
268     /* ------------------------------------------------------------ */
269     public PondLife get(int timeoutMs)
270         throws Exception JavaDoc
271     {
272         PondLife pl=null;
273         
274         // Defer to other threads before locking
275
if (_available<_min)
276             Thread.yield();
277         
278         int new_id=-1;
279         
280         // Try to get pondlife without creating new one.
281
synchronized(this)
282         {
283             // Wait if none available.
284
if (_running>0 && _available==0 && _size==_pondLife.length && timeoutMs>0)
285                 wait(timeoutMs);
286
287             // If still running
288
if (_running>0)
289             {
290                 // if pondlife available
291
if (_available>0)
292                 {
293                     int id=_index[--_available];
294                     pl=_pondLife[id];
295                 }
296                 else if (_size<_pondLife.length)
297                 {
298                     // Reserve spot for a new one
299
new_id=reservePondLife(false);
300                 }
301             }
302
303             // create reserved pondlife
304
if (pl==null && new_id>=0)
305                 pl=newPondLife(new_id);
306         }
307
308         return pl;
309     }
310     
311     
312     /* ------------------------------------------------------------ */
313     public void put(PondLife pl)
314         throws InterruptedException JavaDoc
315     {
316         int id=pl.getID();
317         
318         synchronized(this)
319         {
320             if (_running==0)
321                 stopPondLife(id);
322             else if (_pondLife[id]!=null)
323             {
324                 _index[_available++]=id;
325                 notify();
326             }
327         }
328         
329     }
330     
331     /* ------------------------------------------------------------ */
332     public void shrink()
333         throws InterruptedException JavaDoc
334     {
335         if (_running==0)
336             return;
337
338         synchronized(this)
339         {
340             // If we have a maxIdleTime, then only shrink once per period.
341
if (_maxIdleTimeMs>0)
342             {
343                 long now=System.currentTimeMillis();
344                 if ((now-_lastShrink)<_maxIdleTimeMs)
345                     return; // don't shrink
346
_lastShrink=now;
347             }
348             
349             // shrink if we are running and have available threads and we are above minimal size
350
if (_running>0 && _available>0 && _size>_min)
351                 stopPondLife(_index[--_available]);
352         }
353     }
354
355     /* ------------------------------------------------------------ */
356     private int reservePondLife(boolean available)
357         throws Exception JavaDoc
358     {
359         int id=-1;
360         synchronized(this)
361         {
362             id=_index[_size++];
363             if (available)
364                 _index[_available++]=id;
365         }
366         return id;
367     }
368     
369     /* ------------------------------------------------------------ */
370     private PondLife newPondLife(int id)
371         throws Exception JavaDoc
372     {
373         PondLife pl= (PondLife)_class.newInstance();
374         _pondLife[id]=pl;
375         pl.enterPool(this,id);
376         return pl;
377     }
378
379     /* ------------------------------------------------------------ */
380     private PondLife newPondLife()
381         throws Exception JavaDoc
382     {
383         return newPondLife(reservePondLife(true));
384     }
385     
386     /* ------------------------------------------------------------ */
387     private void closePondLife(int id)
388     {
389         if (_pondLife[id]!=null)
390             _pondLife[id].poolClosing();
391     }
392     
393     /* ------------------------------------------------------------ */
394     private void stopPondLife(int id)
395     {
396         PondLife pl = null;
397         synchronized(this)
398         {
399             pl=_pondLife[id];
400             if (pl!=null)
401             {
402                 _pondLife[id]=null;
403                 _index[--_size]=id;
404                 if (_available>_size)
405                     _available=_size;
406             }
407         }
408         if (pl!=null)
409             pl.leavePool();
410     }
411
412     /* ------------------------------------------------------------ */
413     public void dump(String JavaDoc msg)
414     {
415         StringBuffer JavaDoc pond=new StringBuffer JavaDoc();
416         StringBuffer JavaDoc avail=new StringBuffer JavaDoc();
417         StringBuffer JavaDoc index=new StringBuffer JavaDoc();
418         
419          pond.append("pond: ");
420          avail.append("avail:");
421          index.append("index:");
422         
423         for (int i=0;i<_pondLife.length;i++)
424         {
425             if (_pondLife[i]==null)
426                 pond.append(" ");
427             else
428             {
429                 pond.append(' ');
430                 StringUtil.append(pond,(byte)i,16);
431             }
432             
433             if (i==_size)
434                 avail.append(i==_available?" AS":" S");
435             else
436                 avail.append(i==_available?" A ":" ");
437             
438             index.append(' ');
439             StringUtil.append(index,(byte)_index[i],16);
440         }
441
442         System.err.println();
443         System.err.println(msg);
444         System.err.println(pond);
445         System.err.println(avail);
446         System.err.println(index);
447     }
448     
449     
450     /* ------------------------------------------------------------ */
451     private void readObject(java.io.ObjectInputStream JavaDoc in)
452         throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc
453     {
454         in.defaultReadObject();
455         if (_class==null || !_class.getName().equals(_className))
456         {
457             try
458             {
459                 setPoolClass(Loader.loadClass(Pool.class,_className));
460             }
461             catch (Exception JavaDoc e)
462             {
463                 log.warn(LogSupport.EXCEPTION,e);
464                 throw new java.io.InvalidObjectException JavaDoc(e.toString());
465             }
466         }
467     }
468 }
469
Popular Tags