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