Mercurial > sdl-ios-xcode
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: */ |