comparison src/timer/SDL_timer.c @ 5074:906d7293bb47

Fixed bug in timer when the list of timers changed. Fix contributed by Michael Bicha
author Sam Lantinga <slouken@libsdl.org>
date Sat, 22 Jan 2011 00:33:37 -0800
parents f7b03b6838cb
children 481dabb098ef
comparison
equal deleted inserted replaced
5073:1e94e68525d5 5074:906d7293bb47
111 Uint32 now, ms; 111 Uint32 now, ms;
112 SDL_TimerID t, prev, next; 112 SDL_TimerID t, prev, next;
113 SDL_bool removed; 113 SDL_bool removed;
114 114
115 SDL_mutexP(SDL_timer_mutex); 115 SDL_mutexP(SDL_timer_mutex);
116 list_changed = SDL_FALSE; 116
117 now = SDL_GetTicks(); 117 now = SDL_GetTicks();
118 for (prev = NULL, t = SDL_timers; t; t = next) { 118 do {
119 removed = SDL_FALSE; 119 list_changed = SDL_FALSE;
120 ms = t->interval - SDL_TIMESLICE; 120 for (prev = NULL, t = SDL_timers; t; t = next) {
121 next = t->next; 121 removed = SDL_FALSE;
122 if ((int) (now - t->last_alarm) > (int) ms) { 122 ms = t->interval - SDL_TIMESLICE;
123 struct _SDL_TimerID timer; 123 next = t->next;
124 124 if ((int) (now - t->last_alarm) > (int) ms) {
125 if ((now - t->last_alarm) < t->interval) { 125 struct _SDL_TimerID timer;
126 t->last_alarm += t->interval; 126
127 } else { 127 if ((now - t->last_alarm) < t->interval) {
128 t->last_alarm = now; 128 t->last_alarm += t->interval;
129 }
130 #ifdef DEBUG_TIMERS
131 printf("Executing timer %p (thread = %lu)\n", t, SDL_ThreadID());
132 #endif
133 timer = *t;
134 SDL_mutexV(SDL_timer_mutex);
135 ms = timer.cb(timer.interval, timer.param);
136 SDL_mutexP(SDL_timer_mutex);
137 if (list_changed) {
138 /* Abort, list of timers modified */
139 /* FIXME: what if ms was changed? */
140 break;
141 }
142 if (ms != t->interval) {
143 if (ms) {
144 t->interval = ROUND_RESOLUTION(ms);
145 } else { 129 } else {
146 /* Remove timer from the list */ 130 t->last_alarm = now;
147 #ifdef DEBUG_TIMERS 131 }
148 printf("SDL: Removing timer %p\n", t); 132 #ifdef DEBUG_TIMERS
149 #endif 133 printf("Executing timer %p (thread = %lu)\n",
150 if (prev) { 134 t, SDL_ThreadID());
151 prev->next = next; 135 #endif
136 timer = *t;
137 SDL_mutexV(SDL_timer_mutex);
138 ms = timer.cb(timer.interval, timer.param);
139 SDL_mutexP(SDL_timer_mutex);
140 if (list_changed) {
141 next = t->next;
142 for (prev = SDL_timers; prev; prev = prev->next) {
143 if (prev->next == t)
144 break;
145 }
146 }
147 if (ms != t->interval) {
148 if (ms) {
149 t->interval = ROUND_RESOLUTION(ms);
152 } else { 150 } else {
153 SDL_timers = next; 151 /* Remove timer from the list */
152 #ifdef DEBUG_TIMERS
153 printf("SDL: Removing timer %p\n", t);
154 #endif
155 if (prev) {
156 prev->next = next;
157 } else {
158 SDL_timers = next;
159 }
160 SDL_free(t);
161 --SDL_timer_running;
162 removed = SDL_TRUE;
154 } 163 }
155 SDL_free(t);
156 --SDL_timer_running;
157 removed = SDL_TRUE;
158 } 164 }
159 } 165 if (list_changed) {
160 } 166 /* Abort, list of timers modified */
161 /* Don't update prev if the timer has disappeared */ 167 break;
162 if (!removed) { 168 }
163 prev = t; 169 }
164 } 170 /* Don't update prev if the timer has disappeared */
165 } 171 if (!removed) {
172 prev = t;
173 }
174 }
175 } while (list_changed);
176
166 SDL_mutexV(SDL_timer_mutex); 177 SDL_mutexV(SDL_timer_mutex);
167 } 178 }
168 179
169 static SDL_TimerID 180 static SDL_TimerID
170 SDL_AddTimerInternal(Uint32 interval, SDL_NewTimerCallback callback, 181 SDL_AddTimerInternal(Uint32 interval, SDL_NewTimerCallback callback,