# HG changeset patch # User Sam Lantinga # Date 1295685217 28800 # Node ID 906d7293bb47c5facc53a07abc158dc2d515b960 # Parent 1e94e68525d5f56764dffbfd688aefcf66ca21d0 Fixed bug in timer when the list of timers changed. Fix contributed by Michael Bicha diff -r 1e94e68525d5 -r 906d7293bb47 src/timer/SDL_timer.c --- a/src/timer/SDL_timer.c Fri Jan 21 23:46:51 2011 -0800 +++ b/src/timer/SDL_timer.c Sat Jan 22 00:33:37 2011 -0800 @@ -113,56 +113,67 @@ SDL_bool removed; SDL_mutexP(SDL_timer_mutex); - list_changed = SDL_FALSE; + now = SDL_GetTicks(); - for (prev = NULL, t = SDL_timers; t; t = next) { - removed = SDL_FALSE; - ms = t->interval - SDL_TIMESLICE; - next = t->next; - if ((int) (now - t->last_alarm) > (int) ms) { - struct _SDL_TimerID timer; + do { + list_changed = SDL_FALSE; + for (prev = NULL, t = SDL_timers; t; t = next) { + removed = SDL_FALSE; + ms = t->interval - SDL_TIMESLICE; + next = t->next; + if ((int) (now - t->last_alarm) > (int) ms) { + struct _SDL_TimerID timer; - if ((now - t->last_alarm) < t->interval) { - t->last_alarm += t->interval; - } else { - t->last_alarm = now; - } + if ((now - t->last_alarm) < t->interval) { + t->last_alarm += t->interval; + } else { + t->last_alarm = now; + } #ifdef DEBUG_TIMERS - printf("Executing timer %p (thread = %lu)\n", t, SDL_ThreadID()); + printf("Executing timer %p (thread = %lu)\n", + t, SDL_ThreadID()); #endif - timer = *t; - SDL_mutexV(SDL_timer_mutex); - ms = timer.cb(timer.interval, timer.param); - SDL_mutexP(SDL_timer_mutex); - if (list_changed) { - /* Abort, list of timers modified */ - /* FIXME: what if ms was changed? */ - break; - } - if (ms != t->interval) { - if (ms) { - t->interval = ROUND_RESOLUTION(ms); - } else { - /* Remove timer from the list */ + timer = *t; + SDL_mutexV(SDL_timer_mutex); + ms = timer.cb(timer.interval, timer.param); + SDL_mutexP(SDL_timer_mutex); + if (list_changed) { + next = t->next; + for (prev = SDL_timers; prev; prev = prev->next) { + if (prev->next == t) + break; + } + } + if (ms != t->interval) { + if (ms) { + t->interval = ROUND_RESOLUTION(ms); + } else { + /* Remove timer from the list */ #ifdef DEBUG_TIMERS - printf("SDL: Removing timer %p\n", t); + printf("SDL: Removing timer %p\n", t); #endif - if (prev) { - prev->next = next; - } else { - SDL_timers = next; + if (prev) { + prev->next = next; + } else { + SDL_timers = next; + } + SDL_free(t); + --SDL_timer_running; + removed = SDL_TRUE; } - SDL_free(t); - --SDL_timer_running; - removed = SDL_TRUE; + } + if (list_changed) { + /* Abort, list of timers modified */ + break; } } + /* Don't update prev if the timer has disappeared */ + if (!removed) { + prev = t; + } } - /* Don't update prev if the timer has disappeared */ - if (!removed) { - prev = t; - } - } + } while (list_changed); + SDL_mutexV(SDL_timer_mutex); }