KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > util > timeout > TimeoutFactory


1 /*
2  * JBoss, Home of Professional Open Source
3  * Copyright 2005, JBoss Inc., and individual contributors as indicated
4  * by the @authors tag. See the copyright.txt in the distribution for a
5  * full listing of individual contributors.
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this software; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21  */

22 package org.jboss.util.timeout;
23
24 import org.jboss.util.NestedRuntimeException;
25 import org.jboss.util.ThrowableHandler;
26 import org.jboss.util.threadpool.BasicThreadPool;
27 import org.jboss.util.threadpool.BlockingMode;
28 import org.jboss.util.threadpool.ThreadPool;
29
30 import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
31
32 /**
33  * The timeout factory.
34  *
35  * @author <a HREF="osh@sparre.dk">Ole Husgaard</a>
36  * @author <a HREF="dimitris@jboss.org">Dimitris Andreadis</a>
37  * @author <a HREF="genman@maison-otaku.net">Elias Ross</a>
38  * @author <a HREF="adrian@jboss.com">Adrian Brock</a>
39  * @version $Revision: 1958 $
40  */

41 public class TimeoutFactory
42 {
43    /** The priority queue property */
44    private static final String JavaDoc priorityQueueProperty = TimeoutPriorityQueue.class.getName();
45
46    /** The priority queue default */
47    private static final String JavaDoc priorityQueueName = TimeoutPriorityQueueImpl.class.getName();
48    
49    /** Our singleton instance */
50    private static TimeoutFactory singleton;
51    
52    /** Number of TimeoutFactories created */
53    private static int timeoutFactoriesCount = 0;
54    
55    /** The priority queue class */
56    private static Class JavaDoc priorityQueueClass;
57    
58    /** The default threadpool used to execute timeouts */
59    private static BasicThreadPool DEFAULT_TP = new BasicThreadPool("Timeouts");
60    static
61    {
62       DEFAULT_TP.setBlockingMode(BlockingMode.RUN);
63
64       String JavaDoc priorityQueueClassName = priorityQueueName;
65       ClassLoader JavaDoc cl = TimeoutFactory.class.getClassLoader();
66       try
67       {
68          priorityQueueClassName = System.getProperty(priorityQueueProperty, priorityQueueName);
69          cl = Thread.currentThread().getContextClassLoader();
70       }
71       catch (Exception JavaDoc ignored)
72       {
73       }
74       
75       try
76       {
77          priorityQueueClass = cl.loadClass(priorityQueueClassName);
78       }
79       catch (Exception JavaDoc e)
80       {
81          throw new NestedRuntimeException(e.toString(), e);
82       }
83    }
84
85    /** Used for graceful exiting */
86    private SynchronizedBoolean cancelled = new SynchronizedBoolean(false);
87    
88    /** The daemon thread that dequeues timeouts tasks and issues
89        them for execution to the thread pool */

90    private Thread JavaDoc workerThread;
91    
92    /** Per TimeoutFactory thread pool used to execute timeouts */
93    private ThreadPool threadPool;
94    
95    /** The priority queue */
96    private TimeoutPriorityQueue queue;
97
98    /** Lazy constructions of the TimeoutFactory singleton */
99    public synchronized static TimeoutFactory getSingleton()
100    {
101       if (singleton == null)
102       {
103          singleton = new TimeoutFactory(DEFAULT_TP);
104       }
105       return singleton;
106    }
107    
108    /**
109     * Schedules a new timeout using the singleton TimeoutFactory
110     */

111    static public Timeout createTimeout(long time, TimeoutTarget target)
112    {
113       return getSingleton().schedule(time, target);
114    }
115    
116    /**
117     * Constructs a new TimeoutFactory that uses the provided ThreadPool
118     */

119    public TimeoutFactory(ThreadPool threadPool)
120    {
121       this.threadPool = threadPool;
122       try
123       {
124          queue = (TimeoutPriorityQueue) priorityQueueClass.newInstance();
125       }
126       catch (Exception JavaDoc e)
127       {
128          throw new RuntimeException JavaDoc("Cannot instantiate " + priorityQueueClass,e);
129       }
130       
131       // setup the workerThread
132
workerThread = new Thread JavaDoc("TimeoutFactory-" + timeoutFactoriesCount++)
133       {
134          public void run()
135          {
136             doWork();
137          }
138       };
139       workerThread.setDaemon(true);
140       workerThread.start();
141    }
142    
143    /**
144     * Constructs a new TimeoutFactory that uses the default thread pool
145     */

146    public TimeoutFactory()
147    {
148       this(DEFAULT_TP);
149    }
150    
151    /**
152     * Schedules a new timeout.
153     *
154     * @param time absolute time
155     * @param target target to fire
156     */

157    public Timeout schedule(long time, TimeoutTarget target)
158    {
159       if (cancelled.get())
160          throw new IllegalStateException JavaDoc("TimeoutFactory has been cancelled");
161       if (time < 0)
162          throw new IllegalArgumentException JavaDoc("Negative time");
163       if (target == null)
164          throw new IllegalArgumentException JavaDoc("Null timeout target");
165
166       return queue.offer(time, target);
167    }
168    
169    /**
170     * Schedules a new timeout.
171     *
172     * @param time absolute time
173     * @param run runnable to run
174     */

175    public Timeout schedule(long time, Runnable JavaDoc run)
176    {
177       return schedule(time, new TimeoutTargetImpl(run));
178    }
179    
180    /**
181     * Cancels all submitted tasks, stops the worker
182     * thread and clean-ups everything except for the
183     * thread pool. Scheduling new timeouts after cancel
184     * is called results in a IllegalStateException.
185     */

186    public void cancel()
187    {
188       // obviously the singleton TimeoutFactory cannot
189
// be cancelled since its reference is not accessible
190

191       // let the worker thread cleanup
192
if (cancelled.set(true) == false);
193       {
194          // Cancel the priority queue
195
queue.cancel();
196       }
197    }
198    
199    /**
200     * Returns true if the TimeoutFactory has been cancelled,
201     * false if it is operational (i.e. accepts timeout schedules).
202     */

203    public boolean isCancelled()
204    {
205       return cancelled.get();
206    }
207
208    /**
209     * Timeout worker method.
210     */

211    private void doWork()
212    {
213       while (cancelled.get() == false)
214       {
215          TimeoutExt work = queue.take();
216          // Do work, if any
217
if (work != null)
218          {
219             // Wrap the TimeoutExt with a runnable that invokes the target callback
220
TimeoutWorker worker = new TimeoutWorker(work);
221             try
222             {
223                threadPool.run(worker);
224             }
225             catch (Throwable JavaDoc t)
226             {
227                // protect the worker thread from pool enqueue errors
228
ThrowableHandler.add(ThrowableHandler.Type.ERROR, t);
229             }
230             synchronized (work)
231             {
232                work.done();
233             }
234          }
235       }
236       
237       // TimeoutFactory was cancelled
238
queue.cancel();
239    }
240    
241    /**
242     * A runnable that fires the timeout callback
243     */

244    private static class TimeoutWorker implements Runnable JavaDoc
245    {
246       private TimeoutExt work;
247
248       /**
249        * Create a new instance.
250        *
251        * @param work The timeout that should be fired.
252        */

253       TimeoutWorker(TimeoutExt work)
254       {
255          this.work = work;
256       }
257
258       /**
259        * Override to fire the timeout.
260        */

261       public void run()
262       {
263          try
264          {
265             work.getTimeoutTarget().timedOut(work);
266          }
267          catch (Throwable JavaDoc t)
268          {
269             // protect the thread pool thread from receiving this error
270
ThrowableHandler.add(ThrowableHandler.Type.ERROR, t);
271          }
272          synchronized (work)
273          {
274             work.done();
275          }
276       }
277    }
278    
279    /**
280     * Simple TimeoutTarget implementation that wraps a Runnable
281     */

282    private static class TimeoutTargetImpl implements TimeoutTarget
283    {
284       Runnable JavaDoc runnable;
285       
286       TimeoutTargetImpl(Runnable JavaDoc runnable)
287       {
288          this.runnable = runnable;
289       }
290       
291       public void timedOut(Timeout ignored)
292       {
293          runnable.run();
294       }
295    }
296 }
Popular Tags