comparison src/timer/SDL_timer.c @ 1895:c121d94672cb

SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 10 Jul 2006 21:04:37 +0000
parents e02263385643
children 99210400e8b9
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
36 SDL_TimerCallback SDL_alarm_callback; 36 SDL_TimerCallback SDL_alarm_callback;
37 37
38 /* Data used for a thread-based timer */ 38 /* Data used for a thread-based timer */
39 static int SDL_timer_threaded = 0; 39 static int SDL_timer_threaded = 0;
40 40
41 struct _SDL_TimerID { 41 struct _SDL_TimerID
42 Uint32 interval; 42 {
43 SDL_NewTimerCallback cb; 43 Uint32 interval;
44 void *param; 44 SDL_NewTimerCallback cb;
45 Uint32 last_alarm; 45 void *param;
46 struct _SDL_TimerID *next; 46 Uint32 last_alarm;
47 struct _SDL_TimerID *next;
47 }; 48 };
48 49
49 static SDL_TimerID SDL_timers = NULL; 50 static SDL_TimerID SDL_timers = NULL;
50 static SDL_mutex *SDL_timer_mutex; 51 static SDL_mutex *SDL_timer_mutex;
51 static volatile SDL_bool list_changed = SDL_FALSE; 52 static volatile SDL_bool list_changed = SDL_FALSE;
52 53
53 /* Set whether or not the timer should use a thread. 54 /* Set whether or not the timer should use a thread.
54 This should not be called while the timer subsystem is running. 55 This should not be called while the timer subsystem is running.
55 */ 56 */
56 int SDL_SetTimerThreaded(int value) 57 int
57 { 58 SDL_SetTimerThreaded(int value)
58 int retval; 59 {
59 60 int retval;
60 if ( SDL_timer_started ) { 61
61 SDL_SetError("Timer already initialized"); 62 if (SDL_timer_started) {
62 retval = -1; 63 SDL_SetError("Timer already initialized");
63 } else { 64 retval = -1;
64 retval = 0; 65 } else {
65 SDL_timer_threaded = value; 66 retval = 0;
66 } 67 SDL_timer_threaded = value;
67 return retval; 68 }
68 } 69 return retval;
69 70 }
70 int SDL_TimerInit(void) 71
71 { 72 int
72 int retval; 73 SDL_TimerInit(void)
73 74 {
74 retval = 0; 75 int retval;
75 if ( SDL_timer_started ) { 76
76 SDL_TimerQuit(); 77 retval = 0;
77 } 78 if (SDL_timer_started) {
78 if ( ! SDL_timer_threaded ) { 79 SDL_TimerQuit();
79 retval = SDL_SYS_TimerInit(); 80 }
80 } 81 if (!SDL_timer_threaded) {
81 if ( SDL_timer_threaded ) { 82 retval = SDL_SYS_TimerInit();
82 SDL_timer_mutex = SDL_CreateMutex(); 83 }
83 } 84 if (SDL_timer_threaded) {
84 if ( retval == 0 ) { 85 SDL_timer_mutex = SDL_CreateMutex();
85 SDL_timer_started = 1; 86 }
86 } 87 if (retval == 0) {
87 return(retval); 88 SDL_timer_started = 1;
88 } 89 }
89 90 return (retval);
90 void SDL_TimerQuit(void) 91 }
91 { 92
92 SDL_SetTimer(0, NULL); 93 void
93 if ( SDL_timer_threaded < 2 ) { 94 SDL_TimerQuit(void)
94 SDL_SYS_TimerQuit(); 95 {
95 } 96 SDL_SetTimer(0, NULL);
96 if ( SDL_timer_threaded ) { 97 if (SDL_timer_threaded < 2) {
97 SDL_DestroyMutex(SDL_timer_mutex); 98 SDL_SYS_TimerQuit();
98 SDL_timer_mutex = NULL; 99 }
99 } 100 if (SDL_timer_threaded) {
100 SDL_timer_started = 0; 101 SDL_DestroyMutex(SDL_timer_mutex);
101 SDL_timer_threaded = 0; 102 SDL_timer_mutex = NULL;
102 } 103 }
103 104 SDL_timer_started = 0;
104 void SDL_ThreadedTimerCheck(void) 105 SDL_timer_threaded = 0;
105 { 106 }
106 Uint32 now, ms; 107
107 SDL_TimerID t, prev, next; 108 void
108 SDL_bool removed; 109 SDL_ThreadedTimerCheck(void)
109 110 {
110 SDL_mutexP(SDL_timer_mutex); 111 Uint32 now, ms;
111 list_changed = SDL_FALSE; 112 SDL_TimerID t, prev, next;
112 now = SDL_GetTicks(); 113 SDL_bool removed;
113 for ( prev = NULL, t = SDL_timers; t; t = next ) { 114
114 removed = SDL_FALSE; 115 SDL_mutexP(SDL_timer_mutex);
115 ms = t->interval - SDL_TIMESLICE; 116 list_changed = SDL_FALSE;
116 next = t->next; 117 now = SDL_GetTicks();
117 if ( (int)(now - t->last_alarm) > (int)ms ) { 118 for (prev = NULL, t = SDL_timers; t; t = next) {
118 struct _SDL_TimerID timer; 119 removed = SDL_FALSE;
119 120 ms = t->interval - SDL_TIMESLICE;
120 if ( (now - t->last_alarm) < t->interval ) { 121 next = t->next;
121 t->last_alarm += t->interval; 122 if ((int) (now - t->last_alarm) > (int) ms) {
122 } else { 123 struct _SDL_TimerID timer;
123 t->last_alarm = now; 124
124 } 125 if ((now - t->last_alarm) < t->interval) {
125 #ifdef DEBUG_TIMERS 126 t->last_alarm += t->interval;
126 printf("Executing timer %p (thread = %d)\n", 127 } else {
127 t, SDL_ThreadID()); 128 t->last_alarm = now;
128 #endif 129 }
129 timer = *t; 130 #ifdef DEBUG_TIMERS
130 SDL_mutexV(SDL_timer_mutex); 131 printf("Executing timer %p (thread = %d)\n", t, SDL_ThreadID());
131 ms = timer.cb(timer.interval, timer.param); 132 #endif
132 SDL_mutexP(SDL_timer_mutex); 133 timer = *t;
133 if ( list_changed ) { 134 SDL_mutexV(SDL_timer_mutex);
134 /* Abort, list of timers modified */ 135 ms = timer.cb(timer.interval, timer.param);
135 /* FIXME: what if ms was changed? */ 136 SDL_mutexP(SDL_timer_mutex);
136 break; 137 if (list_changed) {
137 } 138 /* Abort, list of timers modified */
138 if ( ms != t->interval ) { 139 /* FIXME: what if ms was changed? */
139 if ( ms ) { 140 break;
140 t->interval = ROUND_RESOLUTION(ms); 141 }
141 } else { 142 if (ms != t->interval) {
142 /* Remove timer from the list */ 143 if (ms) {
143 #ifdef DEBUG_TIMERS 144 t->interval = ROUND_RESOLUTION(ms);
144 printf("SDL: Removing timer %p\n", t); 145 } else {
145 #endif 146 /* Remove timer from the list */
146 if ( prev ) { 147 #ifdef DEBUG_TIMERS
147 prev->next = next; 148 printf("SDL: Removing timer %p\n", t);
148 } else { 149 #endif
149 SDL_timers = next; 150 if (prev) {
150 } 151 prev->next = next;
151 SDL_free(t); 152 } else {
152 --SDL_timer_running; 153 SDL_timers = next;
153 removed = SDL_TRUE; 154 }
154 } 155 SDL_free(t);
155 } 156 --SDL_timer_running;
156 } 157 removed = SDL_TRUE;
157 /* Don't update prev if the timer has disappeared */ 158 }
158 if ( ! removed ) { 159 }
159 prev = t; 160 }
160 } 161 /* Don't update prev if the timer has disappeared */
161 } 162 if (!removed) {
162 SDL_mutexV(SDL_timer_mutex); 163 prev = t;
163 } 164 }
164 165 }
165 static SDL_TimerID SDL_AddTimerInternal(Uint32 interval, SDL_NewTimerCallback callback, void *param) 166 SDL_mutexV(SDL_timer_mutex);
166 { 167 }
167 SDL_TimerID t; 168
168 t = (SDL_TimerID) SDL_malloc(sizeof(struct _SDL_TimerID)); 169 static SDL_TimerID
169 if ( t ) { 170 SDL_AddTimerInternal(Uint32 interval, SDL_NewTimerCallback callback,
170 t->interval = ROUND_RESOLUTION(interval); 171 void *param)
171 t->cb = callback; 172 {
172 t->param = param; 173 SDL_TimerID t;
173 t->last_alarm = SDL_GetTicks(); 174 t = (SDL_TimerID) SDL_malloc(sizeof(struct _SDL_TimerID));
174 t->next = SDL_timers; 175 if (t) {
175 SDL_timers = t; 176 t->interval = ROUND_RESOLUTION(interval);
176 ++SDL_timer_running; 177 t->cb = callback;
177 list_changed = SDL_TRUE; 178 t->param = param;
178 } 179 t->last_alarm = SDL_GetTicks();
179 #ifdef DEBUG_TIMERS 180 t->next = SDL_timers;
180 printf("SDL_AddTimer(%d) = %08x num_timers = %d\n", interval, (Uint32)t, SDL_timer_running); 181 SDL_timers = t;
181 #endif 182 ++SDL_timer_running;
182 return t; 183 list_changed = SDL_TRUE;
183 } 184 }
184 185 #ifdef DEBUG_TIMERS
185 SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param) 186 printf("SDL_AddTimer(%d) = %08x num_timers = %d\n", interval, (Uint32) t,
186 { 187 SDL_timer_running);
187 SDL_TimerID t; 188 #endif
188 if ( ! SDL_timer_mutex ) { 189 return t;
189 if ( SDL_timer_started ) { 190 }
190 SDL_SetError("This platform doesn't support multiple timers"); 191
191 } else { 192 SDL_TimerID
192 SDL_SetError("You must call SDL_Init(SDL_INIT_TIMER) first"); 193 SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param)
193 } 194 {
194 return NULL; 195 SDL_TimerID t;
195 } 196 if (!SDL_timer_mutex) {
196 if ( ! SDL_timer_threaded ) { 197 if (SDL_timer_started) {
197 SDL_SetError("Multiple timers require threaded events!"); 198 SDL_SetError("This platform doesn't support multiple timers");
198 return NULL; 199 } else {
199 } 200 SDL_SetError("You must call SDL_Init(SDL_INIT_TIMER) first");
200 SDL_mutexP(SDL_timer_mutex); 201 }
201 t = SDL_AddTimerInternal(interval, callback, param); 202 return NULL;
202 SDL_mutexV(SDL_timer_mutex); 203 }
203 return t; 204 if (!SDL_timer_threaded) {
204 } 205 SDL_SetError("Multiple timers require threaded events!");
205 206 return NULL;
206 SDL_bool SDL_RemoveTimer(SDL_TimerID id) 207 }
207 { 208 SDL_mutexP(SDL_timer_mutex);
208 SDL_TimerID t, prev = NULL; 209 t = SDL_AddTimerInternal(interval, callback, param);
209 SDL_bool removed; 210 SDL_mutexV(SDL_timer_mutex);
210 211 return t;
211 removed = SDL_FALSE; 212 }
212 SDL_mutexP(SDL_timer_mutex); 213
213 /* Look for id in the linked list of timers */ 214 SDL_bool
214 for (t = SDL_timers; t; prev=t, t = t->next ) { 215 SDL_RemoveTimer(SDL_TimerID id)
215 if ( t == id ) { 216 {
216 if(prev) { 217 SDL_TimerID t, prev = NULL;
217 prev->next = t->next; 218 SDL_bool removed;
218 } else { 219
219 SDL_timers = t->next; 220 removed = SDL_FALSE;
220 } 221 SDL_mutexP(SDL_timer_mutex);
221 SDL_free(t); 222 /* Look for id in the linked list of timers */
222 --SDL_timer_running; 223 for (t = SDL_timers; t; prev = t, t = t->next) {
223 removed = SDL_TRUE; 224 if (t == id) {
224 list_changed = SDL_TRUE; 225 if (prev) {
225 break; 226 prev->next = t->next;
226 } 227 } else {
227 } 228 SDL_timers = t->next;
228 #ifdef DEBUG_TIMERS 229 }
229 printf("SDL_RemoveTimer(%08x) = %d num_timers = %d thread = %d\n", (Uint32)id, removed, SDL_timer_running, SDL_ThreadID()); 230 SDL_free(t);
230 #endif 231 --SDL_timer_running;
231 SDL_mutexV(SDL_timer_mutex); 232 removed = SDL_TRUE;
232 return removed; 233 list_changed = SDL_TRUE;
234 break;
235 }
236 }
237 #ifdef DEBUG_TIMERS
238 printf("SDL_RemoveTimer(%08x) = %d num_timers = %d thread = %d\n",
239 (Uint32) id, removed, SDL_timer_running, SDL_ThreadID());
240 #endif
241 SDL_mutexV(SDL_timer_mutex);
242 return removed;
233 } 243 }
234 244
235 /* Old style callback functions are wrapped through this */ 245 /* Old style callback functions are wrapped through this */
236 static Uint32 SDLCALL callback_wrapper(Uint32 ms, void *param) 246 static Uint32 SDLCALL
237 { 247 callback_wrapper(Uint32 ms, void *param)
238 SDL_TimerCallback func = (SDL_TimerCallback) param; 248 {
239 return (*func)(ms); 249 SDL_TimerCallback func = (SDL_TimerCallback) param;
240 } 250 return (*func) (ms);
241 251 }
242 int SDL_SetTimer(Uint32 ms, SDL_TimerCallback callback) 252
243 { 253 int
244 int retval; 254 SDL_SetTimer(Uint32 ms, SDL_TimerCallback callback)
245 255 {
246 #ifdef DEBUG_TIMERS 256 int retval;
247 printf("SDL_SetTimer(%d)\n", ms); 257
248 #endif 258 #ifdef DEBUG_TIMERS
249 retval = 0; 259 printf("SDL_SetTimer(%d)\n", ms);
250 260 #endif
251 if ( SDL_timer_threaded ) { 261 retval = 0;
252 SDL_mutexP(SDL_timer_mutex); 262
253 } 263 if (SDL_timer_threaded) {
254 if ( SDL_timer_running ) { /* Stop any currently running timer */ 264 SDL_mutexP(SDL_timer_mutex);
255 if ( SDL_timer_threaded ) { 265 }
256 while ( SDL_timers ) { 266 if (SDL_timer_running) { /* Stop any currently running timer */
257 SDL_TimerID freeme = SDL_timers; 267 if (SDL_timer_threaded) {
258 SDL_timers = SDL_timers->next; 268 while (SDL_timers) {
259 SDL_free(freeme); 269 SDL_TimerID freeme = SDL_timers;
260 } 270 SDL_timers = SDL_timers->next;
261 SDL_timer_running = 0; 271 SDL_free(freeme);
262 list_changed = SDL_TRUE; 272 }
263 } else { 273 SDL_timer_running = 0;
264 SDL_SYS_StopTimer(); 274 list_changed = SDL_TRUE;
265 SDL_timer_running = 0; 275 } else {
266 } 276 SDL_SYS_StopTimer();
267 } 277 SDL_timer_running = 0;
268 if ( ms ) { 278 }
269 if ( SDL_timer_threaded ) { 279 }
270 if ( SDL_AddTimerInternal(ms, callback_wrapper, (void *)callback) == NULL ) { 280 if (ms) {
271 retval = -1; 281 if (SDL_timer_threaded) {
272 } 282 if (SDL_AddTimerInternal
273 } else { 283 (ms, callback_wrapper, (void *) callback) == NULL) {
274 SDL_timer_running = 1; 284 retval = -1;
275 SDL_alarm_interval = ms; 285 }
276 SDL_alarm_callback = callback; 286 } else {
277 retval = SDL_SYS_StartTimer(); 287 SDL_timer_running = 1;
278 } 288 SDL_alarm_interval = ms;
279 } 289 SDL_alarm_callback = callback;
280 if ( SDL_timer_threaded ) { 290 retval = SDL_SYS_StartTimer();
281 SDL_mutexV(SDL_timer_mutex); 291 }
282 } 292 }
283 293 if (SDL_timer_threaded) {
284 return retval; 294 SDL_mutexV(SDL_timer_mutex);
285 } 295 }
296
297 return retval;
298 }
299
300 /* vi: set ts=4 sw=4 expandtab: */