KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas_timer > TimerManager


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * Initial developer(s): ____________________________________.
22  * Contributor(s): ______________________________________.
23  *
24  * --------------------------------------------------------------------------
25  * $Id: TimerManager.java,v 1.14 2005/04/28 16:53:00 benoitf Exp $
26  * --------------------------------------------------------------------------
27  */

28
29
30 package org.objectweb.jonas_timer;
31
32 import java.util.ArrayList JavaDoc;
33 import java.util.Collection JavaDoc;
34 import java.util.Iterator JavaDoc;
35
36 import org.objectweb.util.monolog.api.BasicLevel;
37
38 /**
39  * Clock thread for a TimerManager
40  * Every second, decrement timers and launch action if expired
41  */

42 class Clock extends Thread JavaDoc {
43
44     private TimerManager tmgr;
45
46     public Clock(TimerManager tmgr) {
47         super("JonasClock");
48         if (TraceTimer.isDebug()) {
49             TraceTimer.logger.log(BasicLevel.DEBUG, "Clock constructor");
50         }
51         this.tmgr = tmgr;
52     }
53
54     public void run() {
55         tmgr.clock();
56     }
57 }
58
59 /**
60  * Batch thread for a TimerManager
61  * pocess all expired timers
62  */

63 class Batch extends Thread JavaDoc {
64
65     private TimerManager tmgr;
66
67     public Batch(TimerManager tmgr) {
68         super("JonasBatch");
69         if (TraceTimer.isDebug()) {
70             TraceTimer.logger.log(BasicLevel.DEBUG, "Batch constructor");
71         }
72         this.tmgr = tmgr;
73     }
74
75     public void run() {
76         tmgr.batch();
77     }
78 }
79
80 /**
81  * A timer manager manages 2 lists of timers with 2 threads
82  * One thread is a clock which decrements timers every second
83  * and passes them when expired in a list of expired timers.
84  * The other thread looks in the list of expired timers to process
85  * them.
86  */

87 public class TimerManager {
88
89     // threads managing the service.
90
private static Batch batchThread;
91     private static Clock clockThread;
92
93     private final static long PERIOD_MAX = 30000; // 30 sec
94
private final static long PERIOD_MIN = 100; // 1/10 sec
95
private long period;
96     private long minremtime = PERIOD_MAX;
97
98     // lists
99
private ArrayList JavaDoc timerList = new ArrayList JavaDoc();
100     private ArrayList JavaDoc expiredList = new ArrayList JavaDoc();
101
102     private static TimerManager unique = null;
103     private static boolean shuttingdown = false;
104
105     /**
106      * Constructor
107      */

108     private TimerManager() {
109         // launch threads for timers
110
batchThread = new Batch(this);
111         batchThread.start();
112         clockThread = new Clock(this);
113         clockThread.start();
114     }
115
116     /**
117      * Get an instance of the TimerManager
118      */

119     public static TimerManager getInstance() {
120         if (unique == null)
121             unique = new TimerManager();
122         return unique;
123     }
124
125     /**
126      * stop the service
127      * @param force tell the manager NOT to wait for the timers to be completed
128      */

129     public static void stop(boolean force) {
130         if (TraceTimer.isDebug()) {
131             TraceTimer.logger.log(BasicLevel.DEBUG,"Stop TimerManager");
132         }
133         TimerManager tmgr = getInstance();
134         shuttingdown = true;
135         while (clockThread.isAlive() || batchThread.isAlive()) {
136             try {
137                 Thread.sleep(100);
138             } catch (InterruptedException JavaDoc e) {
139                 break;
140             }
141         }
142         if (TraceTimer.isDebug()) {
143             TraceTimer.logger.log(BasicLevel.DEBUG,"TimerManager has stopped");
144         }
145     }
146
147     public static void stop() {
148         stop(true);
149     }
150
151
152     /**
153      * update all timers in the list
154      * each timer expired is put in a special list of expired timers
155      * they will be processed then by the Batch Thread.
156      */

157     public void clock() {
158         synchronized(timerList) {
159             while (true) {
160                 // compute time to sleep
161
if (shuttingdown) {
162                     period = 1;
163                 } else {
164                     period = PERIOD_MAX;
165                     if (minremtime < period) {
166                         period = minremtime < PERIOD_MIN ? PERIOD_MIN : minremtime;
167                     }
168                 }
169                 // must sleep a little less than period
170
try {
171                     timerList.wait(period);
172                 } catch (InterruptedException JavaDoc e) {
173                     TraceTimer.logger.log(BasicLevel.ERROR, "Timer interrupted");
174                 }
175                 int found = 0;
176                 boolean empty = true;
177                 minremtime = PERIOD_MAX;
178                 for (Iterator JavaDoc i = timerList.iterator(); i.hasNext(); ) {
179                     TimerEvent t = (TimerEvent) i.next();
180                     if (!t.isStopped()) {
181                         empty = false;
182                     }
183                     long remtime = t.update();
184                     if (remtime <= 0) {
185                         if (t.valid()) {
186                             expiredList.add(t);
187                             found++;
188                             if (t.ispermanent() && !shuttingdown) {
189                                 remtime = t.restart();
190                                 if (remtime < minremtime) {
191                                     minremtime = remtime;
192                                 }
193                             } else {
194                                 i.remove();
195                             }
196                         } else {
197                             i.remove();
198                         }
199                     } else {
200                         if (remtime < minremtime) {
201                             minremtime = remtime;
202                         }
203                     }
204                     // Be sure there is no more ref on bean in this local variable.
205
t = null;
206                 }
207                 if (found > 0) {
208                     timerList.notifyAll();
209                 } else {
210                     if (empty) {
211                         if (shuttingdown) {
212                             break;
213                         }
214                     }
215                 }
216             }
217             timerList.notifyAll();
218         }
219     }
220
221     /**
222      * process all expired timers
223      */

224     public void batch() {
225
226         while (!(shuttingdown && timerList.isEmpty() && expiredList.isEmpty())) {
227             TimerEvent t;
228             synchronized(timerList) {
229                 while (expiredList.isEmpty()) {
230                     if (shuttingdown) {
231                         TraceTimer.logger.log(BasicLevel.WARN, "TimerManager shutting down");
232                         return;
233                     }
234                     try {
235                         timerList.wait();
236                     } catch (Exception JavaDoc e) {
237                         TraceTimer.logger.log(BasicLevel.ERROR, "Exception in Batch: ",e);
238                     }
239                 }
240                 t = (TimerEvent) expiredList.remove(0);
241             }
242             // Do not keep the lock during the processing of the timer
243
try {
244                 t.process();
245             } catch (Exception JavaDoc e) {
246                 // An exception in a timer process should not stop this thread.
247
TraceTimer.logger.log(BasicLevel.WARN, "Ignoring exception: " + e);
248                 e.printStackTrace();
249             }
250         }
251         TraceTimer.logger.log(BasicLevel.WARN, "TimerManager stopped");
252     }
253
254     /**
255      * add a new timer in the list
256      * @param tel Object that will be notified when the timer expire.
257      * @param timeout nb of seconds before the timer expires.
258      * @param arg info passed with the timer
259      * @param permanent true if the timer is permanent.
260      * @deprecated use addTimerMs instead.
261      */

262     public TimerEvent addTimer(TimerEventListener tel, long timeout, Object JavaDoc arg, boolean permanent) {
263         return addTimerMs(tel, timeout * 1000, arg, permanent);
264     }
265
266     /**
267      * add a new timer in the list
268      * @param tel Object that will be notified when the timer expire.
269      * @param timeout nb of milliseconds before the timer expires.
270      * @param arg info passed with the timer
271      * @param permanent true if the timer is permanent.
272      */

273     public TimerEvent addTimerMs(TimerEventListener tel, long timeout, Object JavaDoc arg, boolean permanent) {
274         TimerEvent te = new TimerEvent(tel, timeout, arg, permanent);
275         synchronized(timerList) {
276             timerList.add(te);
277             if (timeout < minremtime) {
278                 minremtime = timeout;
279             }
280             timerList.notifyAll();
281         }
282         return te;
283     }
284
285     /**
286      * remove a timer from the list. this is not very efficient.
287      * A better way to do this is TimerEvent.unset()
288      * @deprecated
289      */

290     public void removeTimer(TimerEvent te) {
291         synchronized(timerList) {
292             timerList.remove(timerList.indexOf(te));
293         }
294     }
295 }
296
Popular Tags