KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > exolab > jms > common > uuid > Clock


1 /**
2  * Redistribution and use of this software and associated documentation
3  * ("Software"), with or without modification, are permitted provided
4  * that the following conditions are met:
5  *
6  * 1. Redistributions of source code must retain copyright
7  * statements and notices. Redistributions must also contain a
8  * copy of this document.
9  *
10  * 2. Redistributions in binary form must reproduce the
11  * above copyright notice, this list of conditions and the
12  * following disclaimer in the documentation and/or other
13  * materials provided with the distribution.
14  *
15  * 3. The name "Exolab" must not be used to endorse or promote
16  * products derived from this Software without prior written
17  * permission of Intalio. For written permission,
18  * please contact info@exolab.org.
19  *
20  * 4. Products derived from this Software may not be called "Exolab"
21  * nor may "Exolab" appear in their names without prior written
22  * permission of Intalio. Exolab is a registered
23  * trademark of Intalio.
24  *
25  * 5. Due credit should be given to the Exolab Project
26  * (http://www.exolab.org/).
27  *
28  * THIS SOFTWARE IS PROVIDED BY INTALIO AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32  * INTALIO OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39  * OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Copyright 1999-2005 (C) Intalio Inc. All Rights Reserved.
42  *
43  * $Id: Clock.java,v 1.2 2005/03/25 13:22:01 tanderson Exp $
44  */

45 package org.exolab.jms.common.uuid;
46
47 import org.apache.commons.logging.Log;
48 import org.apache.commons.logging.LogFactory;
49
50
51 /**
52  * Provides an efficient mechanism for obtaining the current
53  * system time. Uses a background thread to automatically increment
54  * an internal clock and periodically synchronize with the system clock.
55  * The method {@link #clock clock} is more efficient than
56  * <code>java.lang.System.currentTimeMillis</code>, and also
57  * allows the clock to be artificially advanced for testing purposes.
58  * <p>
59  * The clock is thread-safe and consumes a single thread.
60  * <p>
61  * This class originally came from Tyrex: http://tyrex.sourceforge.net
62  *
63  * @author <a HREF="mailto:arkin@intalio.com">Assaf Arkin</a>
64  * @version $Revision: 1.2 $
65  */

66 public final class Clock extends Thread JavaDoc {
67
68     /**
69      * The number of clock ticks in each unsynchronized cycle.
70      * The default is 100 milliseconds.
71      */

72     public static final int UNSYNCH_TICKS = 100;
73
74
75     /**
76      * The number of unsychronized cycles before the clock is
77      * synchronized with the system clock. The default is 10.
78      */

79     public static final int SYNCH_EVERY = 10;
80
81
82     /**
83      * The current clock.
84      */

85     private static long _clock;
86
87
88     /**
89      * The number of clock ticks to skip before incrementing the internal
90      * clock.
91      */

92     private static int _unsynchTicks = UNSYNCH_TICKS;
93
94     /**
95      * The number of cycles to skip before synchronizing with the system
96      * clock.
97      */

98     private static int _synchEvery = SYNCH_EVERY;
99
100
101     /**
102      * The amount of time in milliseconds by which to advance the clock
103      * compared to the system clock.
104      */

105     private static long _advance;
106
107
108     /**
109      * Used to adjust the clock when it gets out of synch. Based on the
110      * difference between the last clock and the system clock at the point of
111      * synchronization, divided by synchEvery.
112      */

113     private static int _adjust;
114
115     /**
116      * The logger
117      */

118     private static final Log _log = LogFactory.getLog(Clock.class);
119
120
121     /**
122      * Returns the current clock.
123      *
124      * @return The current clock
125      */

126     public static synchronized long clock() {
127         // Synchronization is required since clock is a long.
128
return _clock;
129     }
130
131
132     /**
133      * Sets the number of clock ticks in each unsynchronized cycle.
134      * Use zero to restore the default value.
135      * <p>
136      * The internal clock is advanced every cycle, the length of the
137      * cycle is controlled by this property. A higher value results
138      * in a lower clock resolution.
139      *
140      * @param ticks The number of clock ticks (milliseconds) for
141      * each unsynchronized cycle
142      */

143     public static void setUnsynchTicks(int ticks) {
144         if (ticks <= 0) {
145             ticks = UNSYNCH_TICKS;
146         } else if (ticks < 100) {
147             ticks = 100;
148         }
149         _unsynchTicks = ticks;
150     }
151
152
153     /**
154      * Returns the number of clock ticks in each unsynchronized cycle.
155      *
156      * @return The number of clock ticks (milliseconds) for
157      * each unsynchronized cycle
158      */

159     public static int getUnsynchTicks() {
160         return _unsynchTicks;
161     }
162
163
164     /**
165      * Sets the number of unsynchronized cycles before the clock
166      * is synchronized with the system clock.
167      * <p>
168      * Synchronization will occur every <tt>unsynchTicks * synchEvery</tt>
169      * milliseconds. The larger the value, the less accurate
170      * the clock is.
171      *
172      * @param every The number of unsynchronized cycles
173      */

174     public static void setSynchEvery(int every) {
175         if (every <= 0)
176             every = SYNCH_EVERY;
177         _synchEvery = every;
178     }
179
180
181     /**
182      * Artficially advances the clock.
183      *
184      * @param byMillis The number of milliseconds by which to
185      * advance the clock (must be positive)
186      */

187     public synchronized static void advance(long byMillis) {
188         // Synchronization is required since clock is a long.
189
_advance += byMillis;
190         _clock += byMillis;
191     }
192
193
194     /**
195      * Returns the number of milliseconds by which the clock is
196      * advanced.
197      *
198      * @return The number of milliseconds by which the clock is
199      * advanced
200      */

201     public static long getAdvance() {
202         return _advance;
203     }
204
205
206     public void run() {
207         while (true) {
208             try {
209                 for (int i = 0; i < _synchEvery; ++i) {
210                     sleep(_unsynchTicks);
211                     synchronized (Clock.class) {
212                         _clock += _unsynchTicks + _adjust;
213                     }
214                 }
215                 synchronize();
216             } catch (InterruptedException JavaDoc exception) {
217                 // interrupted - need to resynchronize
218
synchronize();
219             } catch (ThreadDeath JavaDoc exception) {
220                 // allow this to be terminated when Thread.stop() is
221
// invoked. This occurs when applets are destroyed.
222
_log.debug("clock daemon terminating", exception);
223                 throw exception;
224             } catch (Throwable JavaDoc exception) {
225                 _log.error("Internal error in clock daemon", exception);
226             }
227         }
228     }
229
230
231     public static synchronized long synchronize() {
232         long current;
233         long retarded;
234         long clock;
235         int adjust;
236
237         current = System.currentTimeMillis();
238         clock = _clock;
239         retarded = clock - _advance;
240         // Adjust clock to new difference
241
if (current != retarded) {
242             adjust = (int) (current - retarded) / _synchEvery;
243             if (adjust != 0) {
244                 _adjust += adjust;
245                 /*
246                 if ( Configuration.verbose )
247                     Logger.tyrex.debug( "Clock late by " + ( current - retarded ) +
248                                         "ms -> synchronized, adjusting by " + _clock._adjust );
249                 */

250             }
251         }
252         // Make sure clock is progressive
253
if (current > retarded) {
254             clock = current + _advance;
255             _clock = clock;
256         }
257         return clock;
258     }
259
260
261     private Clock() {
262         super("Clock Daemon");
263         _clock = System.currentTimeMillis();
264         setPriority(Thread.MAX_PRIORITY);
265         setDaemon(true);
266         start();
267     }
268
269     static {
270         new Clock();
271     }
272
273     public static void main(String JavaDoc[] args) {
274         long clock;
275         int count;
276
277         try {
278             count = 1000000;
279             System.out.println("Using Clock.clock()");
280             clock = System.currentTimeMillis();
281             for (int i = 0; i < count; ++i) {
282                 if ((i % 100) == 0)
283                     synchronize();
284                 else
285                     clock();
286             }
287             clock = System.currentTimeMillis() - clock;
288             System.out.println("Performed " + count + " in " + clock + "ms");
289             System.out.println("Using System.currentTimeMillis()");
290             clock = System.currentTimeMillis();
291             for (int i = 0; i < count; ++i)
292                 System.currentTimeMillis();
293             clock = System.currentTimeMillis() - clock;
294             System.out.println("Performed " + count + " in " + clock + "ms");
295         } catch (Exception JavaDoc except) {
296         }
297     }
298
299 }
300
Popular Tags