1 /*
2 * RTS periodic timers.
3 *
4 */
5
6 #include "Rts.h"
7 #include "Ticker.h"
8 #include <windows.h>
9 #include <stdio.h>
10 #include <process.h>
11
12 static TickProc tick_proc = NULL;
13 static HANDLE timer_queue = NULL;
14 static HANDLE timer = NULL;
15 static Time tick_interval = 0;
16
tick_callback(PVOID lpParameter STG_UNUSED,BOOLEAN TimerOrWaitFired STG_UNUSED)17 static VOID CALLBACK tick_callback(
18 PVOID lpParameter STG_UNUSED,
19 BOOLEAN TimerOrWaitFired STG_UNUSED
20 )
21 {
22 tick_proc(0);
23 }
24
25 // We use the CreateTimerQueue() API which has been around since
26 // Windows 2000. Apparently it gives bad results before Windows 7,
27 // though: http://www.virtualdub.org/blog/pivot/entry.php?id=272
28 //
29 // Even with the improvements in Windows 7, this timer isn't going to
30 // be very useful for profiling with a max usable resolution of
31 // 15ms. Unfortunately we don't have anything better.
32
33 void
initTicker(Time interval,TickProc handle_tick)34 initTicker (Time interval, TickProc handle_tick)
35 {
36 tick_interval = interval;
37 tick_proc = handle_tick;
38
39 timer_queue = CreateTimerQueue();
40 if (timer_queue == NULL) {
41 sysErrorBelch("CreateTimerQueue");
42 stg_exit(EXIT_FAILURE);
43 }
44 }
45
46 void
startTicker(void)47 startTicker(void)
48 {
49 BOOL r;
50
51 r = CreateTimerQueueTimer(&timer,
52 timer_queue,
53 tick_callback,
54 0,
55 0,
56 TimeToUS(tick_interval) / 1000, // ms
57 WT_EXECUTEINTIMERTHREAD);
58 if (r == 0) {
59 sysErrorBelch("CreateTimerQueueTimer");
60 stg_exit(EXIT_FAILURE);
61 }
62 }
63
64 void
stopTicker(void)65 stopTicker(void)
66 {
67 if (timer_queue != NULL && timer != NULL) {
68 DeleteTimerQueueTimer(timer_queue, timer, NULL);
69 timer = NULL;
70 }
71 }
72
73 void
exitTicker(bool wait)74 exitTicker (bool wait)
75 {
76 stopTicker();
77 if (timer_queue != NULL) {
78 DeleteTimerQueueEx(timer_queue, wait ? INVALID_HANDLE_VALUE : NULL);
79 timer_queue = NULL;
80 }
81 }
82