- while (it != it2) {
- if ((*it)->when <= now) {
- wd.func = (*it)->function;
- scm_internal_catch(SCM_BOOL_T,
- (scm_t_catch_body) Interp::LazyApplyWrapper, (void *)&wd,
- (scm_t_catch_handler) Interp::EmptyHandler, 0);
- scm_gc_unprotect_object(wd.func);
- it3 = it;
- ++it3;
- delete (*it);
- timersList.erase(it);
- it = it3;
- } else {
- ++it;
+ while (!timers.empty ())
+ {
+ // Keep a stack allocated copy of the front of the timer queue
+ // just in case the timer is deleted while being executed (which
+ // is very unlikely as the only place this could occur is if the
+ // timer deleted itself)
+ Timer current_timer = *timers.front () ;
+
+ if (current_timer.when <= now)
+ {
+ wd.func = current_timer.function;
+
+ scm_internal_catch (SCM_BOOL_T,
+ (scm_t_catch_body) Interp::LazyApplyWrapper,
+ (void *)&wd,
+ (scm_t_catch_handler) Interp::EmptyHandler,
+ 0);
+
+ // The timer list may have been modified by the timer
+ // callback; if it has in such a way that the first queue
+ // item has changed (adding a timer in the past) then we
+ // switch the slow path for deleting a timer
+ if (current_timer.count == timers.front()->count)
+ {
+ scm_gc_unprotect_object (current_timer.function);
+ delete timers.front ();
+ timers.pop_front ();
+ }
+ else
+ {
+ DelTimer (scm_from_int (current_timer.count));
+ }
+ }
+ else
+ {
+ break;
+ }