1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package net.sf.sensor.timer;
18
19
20 /***
21 * Short-lived, non thread-safe input frontend class for working with timers.
22 * <p>
23 * This class is not thread-safe and for good reasons. The TimerData instance that
24 * is nested inside each Timer instance <b>is</b> thread-safe and is shared between
25 * many seperate instances of Timer. When the {@link #stop()} method is called, a
26 * synchronized call to TimerData.updateStatistics(long)} will be made to
27 * update the "real" timer. After that call, the instance of Timer can be safely
28 * reused or garbage collected.
29 *
30 * @author Age Mooy
31 */
32 public final class Timer {
33
34
35
36
37
38 /*** The TimerData that will be fed with data from the new Timer instance. */
39 private TimerData timerData = null;
40
41 /*** The exact time (in milliseconds since 01-01-1970 00:00) the start method was last called. */
42 private long startTime = 0L;
43
44 /*** Is this instance currently between calls to {@link #start()} and {@link #stop()}. */
45 private boolean isRunning = false;
46
47
48
49
50
51
52 /***
53 * Constructs a new Timer instance for the specified TimerData.
54 * Package private since only TimerData instances are allowed to create Timers.
55 *
56 * @param timerData the TimerData that will be fed with data from the
57 * new Timer instance.
58 */
59 Timer(TimerData timerData) {
60 this.timerData = timerData;
61 }
62
63
64
65
66
67
68 /***
69 * Adds the specified label to the set of labels associated with this instance.
70 * @param label
71 */
72 public void addLabel(String label) {
73 timerData.addLabel(label);
74 }
75
76 /***
77 * Returns the id straight from the nested TimerData.
78 * Unsynchronized since the label is immutable.
79 * @return Returns the label.
80 */
81 public String getId() {
82 return timerData.getId();
83 }
84
85
86
87
88
89
90 /***
91 * Starts the timer. Will not do anything if the timer has already been started
92 * (meaning the {@link #start()} method has been called but the {@link #stop()}
93 * method has not yet been called. For convernience, this method returns the 'this'
94 * reference.
95 *
96 * @return the current instance (the 'this' reference).
97 *
98 * @todo implement runtime detection of java 5 VMs so we can use nanoseconds instead of milliseconds
99 * without becoming java 5 specific or using a multi-target build system
100 */
101 public Timer start() {
102 if (!isRunning) {
103 startTime = System.currentTimeMillis();
104 isRunning = true;
105 }
106
107 return this;
108 }
109
110 /***
111 * Is this Timer instance currently running (ie {@link #start()} was called but
112 * {@link #stop()} was not called yet.
113 * @return true if this Timer instance is in a runing state, false otherwise.
114 */
115 public boolean isRunning() {
116 return isRunning;
117 }
118
119 /***
120 * Stops the timer and reports the time that passed since the first call to
121 * {@link #start()} to the nested TimerData instance.
122 */
123 public void stop() {
124 if (isRunning) {
125
126 timerData.updateFromTimer(System.currentTimeMillis() - startTime);
127
128
129 isRunning = false;
130 }
131 }
132
133 }