jtimer.h
15.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
/***************************************************************************
* Copyright (C) 2005 by Jeff Ferr *
* root@sat *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef J_TIMER_H
#define J_TIMER_H
#include "jthread.h"
#include "jautolock.h"
#include "jdate.h"
#include "jillegalargumentexception.h"
#include "jillegalstateexception.h"
#include <map>
namespace jthread{
/**
* \brief Thread.
*
* @author Jeff Ferr
*/
enum jtimertask_state_t {
JTS_VIRGIN, // The state of this task, chosen from the constants below. This task has not yet been scheduled.
JTS_SCHEDULED, // This task is scheduled for execution. If it is a non-repeating task, it has not yet been executed.
JTS_EXECUTED, // This non-repeating task has already executed (or is currently executing) and has not been cancelled.
JTS_CANCELLED // This task has been cancelled (with a call to TimerTask.cancel).
};
class Timer;
class TimerThread;
class TaskQueue;
class TimerTask : public jthread::Runnable {
friend class Timer;
friend class TimerThread;
friend class TaskQueue;
private:
jthread::Mutex _mutex;
jtimertask_state_t _state;
uint64_t _delay;
bool _push_time;
protected:
/**
* \brief Creates a new timer task.
*
*/
TimerTask();
public:
uint64_t _next_execution_time;
public:
/**
* \brief
*
*/
virtual ~TimerTask();
/**
* \brief
*
*/
virtual uint64_t GetDelay();
/**
* \brief
*
*/
virtual void SetDelay(uint64_t delay);
/**
* Cancels this timer task. If the task has been scheduled for one-time execution and has not yet run, or
* has not yet been scheduled, it will never run. If the task has been scheduled for repeated execution,
* it will never run again. (If the task is running when this call occurs, the task will run to completion,
* but will never run again.)
*
* <p>Note that calling this method from within the <tt>run</tt> method of a repeating timer task absolutely
* guarantees that the timer task will not run again.
*
* <p>This method may be called repeatedly; the second and subsequent calls have no effect.
*
* @return true if this task is scheduled for one-time execution and has not yet run, or this task is scheduled
* for repeated execution. Returns false if the task was scheduled for one-time execution and has already run,
* or if the task was never scheduled, or if the task was already cancelled. (Loosely speaking, this method
* returns <tt>true</tt> if it prevents one or more scheduled executions from taking place.)
*/
virtual bool Cancel();
/**
* \brief The action to be performed by this timer task.
*
*/
virtual void Run();
};
/**
* \brief This class represents a timer task queue: a priority queue of TimerTasks, ordered on nextExecutionTime.
* Each Timer object has one of these, which it shares with its TimerThread. Internally this class uses a heap,
* which offers log(n) performance for the add, removeMin and rescheduleMin operations, and constant time performance
* for the the getMin operation.
*/
class TaskQueue {
friend class Timer;
friend class TimerThread;
private:
std::vector<TimerTask *> _queue;
jthread::Mutex _mutex;
jthread::Condition _sem;
private:
/**
* \brief Return the "head task" of the priority queue. (The head task is an task with the lowest nextExecutionTime.)
*
*/
TimerTask * GetMin();
/**
* \brief Remove the head task from the priority queue.
*
*/
void RemoveMin();
protected:
/**
* \brief
*
*/
TaskQueue();
public:
/**
* \brief
*
*/
virtual ~TaskQueue();
/**
* \brief Adds a new task to the priority queue.
*
*/
void Add(TimerTask *task);
/**
* \brief Adds a new task to the priority queue.
*
*/
void Remove(TimerTask *task);
/**
* \brief Returns true if the priority queue contains no elements.
*
*/
bool IsEmpty();
/**
* \brief Removes all elements from the priority queue.
*
*/
void Clear();
/**
* \brief
*
*/
int GetSize();
/**
* \brief Sets the nextExecutionTime associated with the head task to the specified value, and adjusts priority
* queue accordingly.
*
*/
void RescheduleMin(uint64_t newTime);
};
/**
* \brief This "helper class" implements the timer's task execution thread, which waits for tasks on the timer queue,
* executions them when they fire, reschedules repeating tasks, and removes cancelled tasks and spent non-repeating
* tasks from the queue.
*
*/
class TimerThread : public jthread::Thread {
friend class Timer;
private:
jthread::Mutex _mutex;
TaskQueue *_queue;
bool _is_running,
_new_tasks_may_be_scheduled;
private:
/**
* \brief The main timer loop.
*
*/
void MainLoop();
protected:
/**
* \brief
*
*/
TimerThread(TaskQueue *queue);
public:
/**
* \brief
*
*/
virtual ~TimerThread();
/**
* \brief
*
*/
virtual void Run();
};
class Timer : public virtual jcommon::Object{
private:
jthread::Mutex _mutex;
TimerThread *_thread;
TaskQueue *_queue;
private:
/**
* \brief Schedule the specifed timer task for execution at the specified time with the specified period, in microseconds.
* If period is positive, the task is scheduled for repeated execution; if period is zero, the task is scheduled for one-time
* execution. Time is specified in Date.getTime() format. This method checks timer state, task state, and initial execution
* time, but not period.
*/
void schedule(TimerTask *task, uint64_t next_execution_time, uint64_t delay, bool push_time);
public:
/**
* \brief Creates a new timer. The associated thread does <i>not</i> run as a daemon.
*
*/
Timer();
/**
* \brief Terminates this timer, discarding any currently scheduled tasks. Does not interfere with a currently
* executing task (if it exists).Once a timer has been terminated, its execution thread terminates gracefully,
* and no more tasks may be scheduled on it.
*
* <p>Note that calling this method from within the run method of a timer task that was invoked by this timer
* absolutely guarantees that the ongoing task execution is the last task execution that will ever be performed
* by this timer.
*
* <p>This method may be called repeatedly; the second and subsequent calls have no effect.
*/
virtual ~Timer();
/**
* \brief Schedules the specified task for execution after the specified delay.
*
* @param task task to be scheduled.
* @param delay delay in microseconds before task is to be executed.
*/
void Schedule(TimerTask *task, uint64_t time, bool delay);
/**
* \brief Schedules the specified task for execution at the specified time. If the time is in the past,
* the task is scheduled for immediate execution.
*
* @param task task to be scheduled.
* @param time time at which task is to be executed.
*/
void Schedule(TimerTask *task, jcommon::Date *time, bool delay);
/**
* \brief Schedules the specified task for repeated <i>fixed-delay execution</i>, beginning after the
* specified delay. Subsequent executions take place at approximately regular intervals separated by the
* specified period.
*
* <p>In fixed-delay execution, each execution is scheduled relative to the actual execution time of the
* previous execution. If an execution is delayed for any reason (such as garbage collection or other
* background activity), subsequent executions will be delayed as well. In the long run, the frequency of
* execution will generally be slightly lower than the reciprocal of the specified period (assuming the system
* clock underlying <tt>Object.wait(long)</tt> is accurate).
*
* <p>Fixed-delay execution is appropriate for recurring activities that require "smoothness." In other
* words, it is appropriate for activities where it is more important to keep the frequency accurate in the
* short run than in the long run. This includes most animation tasks, such as blinking a cursor at regular
* intervals. It also includes tasks wherein regular activity is performed in response to human input, such
* as automatically repeating a character as long as a key is held down.
*
* @param task task to be scheduled.
* @param delay delay in microseconds before task is to be executed.
* @param period time in microseconds between successive task executions.
*/
void Schedule(TimerTask *task, uint64_t time, uint64_t period, bool delay);
/**
* \brief Schedules the specified task for repeated <i>fixed-delay execution</i>, beginning at the specified
* time. Subsequent executions take place at approximately regular intervals, separated by the specified period.
*
* <p>In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous
* execution. If an execution is delayed for any reason (such as garbage collection or other background activity),
* subsequent executions will be delayed as well. In the long run, the frequency of execution will generally be
* slightly lower than the reciprocal of the specified period (assuming the system clock underlying
* <tt>Object.wait(long)</tt> is accurate).
*
* <p>Fixed-delay execution is appropriate for recurring activities that require "smoothness." In other words,
* it is appropriate for activities where it is more important to keep the frequency accurate in the short run
* than in the long run. This includes most animation tasks, such as blinking a cursor at regular intervals. It
* also includes tasks wherein regular activity is performed in response to human input, such as automatically
* repeating a character as long as a key is held down.
*
* @param task task to be scheduled.
* @param firstTime First time at which task is to be executed.
* @param period time in microseconds between successive task executions.
*/
void Schedule(TimerTask *task, jcommon::Date *time, uint64_t period, bool delay);
/**
* \brief Schedules the specified task for repeated <i>fixed-rate execution</i>, beginning after the specified
* delay. Subsequent executions take place at approximately regular intervals, separated by the specified period.
*
* <p>In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial
* execution. If an execution is delayed for any reason (such as garbage collection or other background activity),
* two or more executions will occur in rapid succession to "catch up." In the long run, the frequency of execution
* will be exactly the reciprocal of the specified period (assuming the system clock underlying
* <tt>Object.wait(long)</tt> is accurate).
*
* <p>Fixed-rate execution is appropriate for recurring activities that are sensitive to <i>absolute</i> time,
* such as ringing a chime every hour on the hour, or running scheduled maintenance every day at a particular time.
* It is also appropriate for for recurring activities where the total time to perform a fixed number of executions
* is important, such as a countdown timer that ticks once every second for ten seconds. Finally, fixed-rate
* execution is appropriate for scheduling multiple repeating timer tasks that must remain synchronized with respect
* to one another.
*
* @param task task to be scheduled.
* @param delay delay in microseconds before task is to be executed.
* @param period time in microseconds between successive task executions.
*/
void ScheduleAtFixedRate(TimerTask *task, uint64_t time, uint64_t period, bool delay);
/**
* Schedules the specified task for repeated <i>fixed-rate execution</i>, beginning at the specified time. Subsequent
* executions take place at approximately regular intervals, separated by the specified period.
*
* <p>In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial
* execution. If an execution is delayed for any reason (such as garbage collection or other background activity),
* two or more executions will occur in rapid succession to "catch up." In the long run, the frequency of execution
* will be exactly the reciprocal of the specified period (assuming the system clock underlying
* <tt>Object.wait(long)</tt> is accurate).
*
* <p>Fixed-rate execution is appropriate for recurring activities that are sensitive to <i>absolute</i> time, such
* as ringing a chime every hour on the hour, or running scheduled maintenance every day at a particular time. It is
* also appropriate for for recurring activities where the total time to perform a fixed number of executions is important,
* such as a countdown timer that ticks once every second for ten seconds. Finally, fixed-rate execution is appropriate
* for scheduling multiple repeating timer tasks that must remain synchronized with respect to one another.
*
* @param task task to be scheduled.
* @param firstTime First time at which task is to be executed.
* @param period time in microseconds between successive task executions.
*/
void ScheduleAtFixedRate(TimerTask *task, jcommon::Date *time, uint64_t period, bool delay);
/**
* \brief Remove a schedule reference from timer.
*
*/
void RemoveSchedule(TimerTask *task);
};
}
#endif