comparison src/timer/wince/SDL_systimer.c @ 5113:481dabb098ef

Improved timer implementation The new timer model is formalized as using a separate thread to handle timer callbacks. This was the case on almost every platform before, but it's now a requirement, and simplifies the implementation and makes it perform consistently across platforms. Goals: * Minimize timer thread blocking * Dispatch timers as accurately as possible * SDL_AddTimer() and SDL_RemoveTimer() are completely threadsafe * SDL_RemoveTimer() doesn't crash with a timer that's expired or removed
author Sam Lantinga <slouken@libsdl.org>
date Thu, 27 Jan 2011 14:45:06 -0800
parents 327f181542f1
children b530ef003506
comparison
equal deleted inserted replaced
5112:0846f18eb625 5113:481dabb098ef
22 #include "SDL_config.h" 22 #include "SDL_config.h"
23 23
24 #ifdef SDL_TIMER_WINCE 24 #ifdef SDL_TIMER_WINCE
25 25
26 #include "../../core/windows/SDL_windows.h" 26 #include "../../core/windows/SDL_windows.h"
27 #include <mmsystem.h>
28 27
29 #include "SDL_thread.h"
30 #include "SDL_timer.h" 28 #include "SDL_timer.h"
31 #include "../SDL_timer_c.h"
32 29
33 static Uint64 start_date; 30 static Uint64 start_date;
34 static Uint64 start_ticks; 31 static Uint64 start_ticks;
35 32
36 static Uint64 33 static Uint64
67 wce_rel_date(void) 64 wce_rel_date(void)
68 { 65 {
69 return ((Sint32) (wce_date() - start_date)); 66 return ((Sint32) (wce_date() - start_date));
70 } 67 }
71 68
69 /* Recard start-time of application for reference */
70 void
71 SDL_StartTicks(void)
72 {
73 start_date = wce_date();
74 start_ticks = wce_ticks();
75 }
76
72 /* Return time in ms relative to when SDL was started */ 77 /* Return time in ms relative to when SDL was started */
73 Uint32 78 Uint32
74 SDL_GetTicks() 79 SDL_GetTicks()
75 { 80 {
76 Sint32 offset = wce_rel_date() - wce_rel_ticks(); 81 Sint32 offset = wce_rel_date() - wce_rel_ticks();
87 SDL_Delay(Uint32 ms) 92 SDL_Delay(Uint32 ms)
88 { 93 {
89 Sleep(ms); 94 Sleep(ms);
90 } 95 }
91 96
92 /* Recard start-time of application for reference */ 97 #endif /* SDL_TIMER_WINCE */
93 void
94 SDL_StartTicks(void)
95 {
96 start_date = wce_date();
97 start_ticks = wce_ticks();
98 }
99 98
100 static UINT WIN_timer;
101
102 #if ( _WIN32_WCE <= 420 )
103
104 static HANDLE timersThread = 0;
105 static HANDLE timersQuitEvent = 0;
106
107 DWORD
108 TimersThreadProc(void *data)
109 {
110 while (WaitForSingleObject(timersQuitEvent, 10) == WAIT_TIMEOUT) {
111 SDL_ThreadedTimerCheck();
112 }
113 return 0;
114 }
115
116 int
117 SDL_SYS_TimerInit(void)
118 {
119 // create a thread to process a threaded timers
120 // SetTimer does not suit the needs because
121 // TimerCallbackProc will be called only when WM_TIMER occured
122
123 timersQuitEvent = CreateEvent(0, TRUE, FALSE, 0);
124 if (!timersQuitEvent) {
125 SDL_SetError("Cannot create event for timers thread");
126 return -1;
127 }
128 timersThread = CreateThread(NULL, 0, TimersThreadProc, 0, 0, 0);
129 if (!timersThread) {
130 SDL_SetError
131 ("Cannot create timers thread, check amount of RAM available");
132 return -1;
133 }
134 SetThreadPriority(timersThread, THREAD_PRIORITY_HIGHEST);
135
136 return (SDL_SetTimerThreaded(1));
137 }
138
139 void
140 SDL_SYS_TimerQuit(void)
141 {
142 SetEvent(timersQuitEvent);
143 if (WaitForSingleObject(timersThread, 2000) == WAIT_TIMEOUT)
144 TerminateThread(timersThread, 0);
145 CloseHandle(timersThread);
146 CloseHandle(timersQuitEvent);
147 return;
148 }
149
150 #else
151
152 #pragma comment(lib, "mmtimer.lib")
153
154 /* Data to handle a single periodic alarm */
155 static UINT timerID = 0;
156
157 static void CALLBACK
158 HandleAlarm(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
159 {
160 SDL_ThreadedTimerCheck();
161 }
162
163
164 int
165 SDL_SYS_TimerInit(void)
166 {
167 MMRESULT result;
168
169 /* Set timer resolution */
170 result = timeBeginPeriod(TIMER_RESOLUTION);
171 if (result != TIMERR_NOERROR) {
172 SDL_SetError("Warning: Can't set %d ms timer resolution",
173 TIMER_RESOLUTION);
174 }
175 /* Allow 10 ms of drift so we don't chew on CPU */
176 timerID =
177 timeSetEvent(TIMER_RESOLUTION, 1, HandleAlarm, 0, TIME_PERIODIC);
178 if (!timerID) {
179 SDL_SetError("timeSetEvent() failed");
180 return (-1);
181 }
182 return (SDL_SetTimerThreaded(1));
183 }
184
185 void
186 SDL_SYS_TimerQuit(void)
187 {
188 if (timerID) {
189 timeKillEvent(timerID);
190 }
191 timeEndPeriod(TIMER_RESOLUTION);
192 }
193
194 #endif
195
196 int
197 SDL_SYS_StartTimer(void)
198 {
199 SDL_SetError("Internal logic error: WinCE uses threaded timer");
200 return (-1);
201 }
202
203 void
204 SDL_SYS_StopTimer(void)
205 {
206 return;
207 }
208
209 #endif /* SDL_TIMER_WINCE */
210 /* vi: set ts=4 sw=4 expandtab: */ 99 /* vi: set ts=4 sw=4 expandtab: */