don't let repeating timers, with a very fast timer in the queue, cause the main loop to run the timers forever

This commit is contained in:
Dana Jansens 2008-01-15 23:28:30 -05:00
parent 7bd8e97fbb
commit cfc8101333
2 changed files with 21 additions and 4 deletions

View file

@ -104,6 +104,10 @@ struct _ObMainLoopTimer
GTimeVal last; GTimeVal last;
/* When this timer will next trigger */ /* When this timer will next trigger */
GTimeVal timeout; GTimeVal timeout;
/* Only allow a timer's function to fire once per run through the list,
so that it doesn't get locked in there forever */
gboolean fired;
}; };
struct _ObMainLoopSignalHandlerType struct _ObMainLoopSignalHandlerType
@ -558,11 +562,11 @@ void ob_main_loop_timeout_remove_data(ObMainLoop *loop, GSourceFunc handler,
{ {
GSList *it; GSList *it;
ob_debug("removing data 0x%x\n", data);
for (it = loop->timers; it; it = g_slist_next(it)) { for (it = loop->timers; it; it = g_slist_next(it)) {
ObMainLoopTimer *t = it->data; ObMainLoopTimer *t = it->data;
if (t->func == handler && if (t->func == handler && t->equal(t->data, data)) {
(t->equal ? t->equal(t->data, data) : (t->data == data))) ob_debug("found data 0x%x\n", data);
{
t->del_me = TRUE; t->del_me = TRUE;
if (cancel_dest) if (cancel_dest)
t->destroy = NULL; t->destroy = NULL;
@ -599,6 +603,12 @@ static void timer_dispatch(ObMainLoop *loop, GTimeVal **wait)
g_get_current_time(&loop->now); g_get_current_time(&loop->now);
/* do this first, cuz the list can get reordered */
for (it = loop->timers; it; it = g_slist_next(it)) {
ObMainLoopTimer *curr = it->data;
curr->fired = FALSE;
}
for (it = loop->timers; it; it = next) { for (it = loop->timers; it; it = next) {
ObMainLoopTimer *curr; ObMainLoopTimer *curr;
@ -623,6 +633,12 @@ static void timer_dispatch(ObMainLoop *loop, GTimeVal **wait)
if (timecompare(&NEAREST_TIMEOUT(loop), &loop->now) < 0) if (timecompare(&NEAREST_TIMEOUT(loop), &loop->now) < 0)
break; break;
/* don't let it fire again this time around. otherwise, if the first
timer in the queue becomes ready, we'll loop on the later ones
forever if they repeat */
if (curr->fired)
continue;
/* we set the last fired time to delay msec after the previous firing, /* we set the last fired time to delay msec after the previous firing,
then re-insert. timers maintain their order and may trigger more then re-insert. timers maintain their order and may trigger more
than once if they've waited more than one delay's worth of time. than once if they've waited more than one delay's worth of time.
@ -638,6 +654,7 @@ static void timer_dispatch(ObMainLoop *loop, GTimeVal **wait)
g_free(curr); g_free(curr);
} }
curr->fired = TRUE;
fired = TRUE; fired = TRUE;
} }

View file

@ -64,7 +64,7 @@ void ping_start(struct _ObClient *client, ObPingEventHandler h)
ping_send(t); ping_send(t);
ping_targets = g_slist_prepend(ping_targets, t); ping_targets = g_slist_prepend(ping_targets, t);
ob_main_loop_timeout_add(ob_main_loop, PING_TIMEOUT, ping_timeout, ob_main_loop_timeout_add(ob_main_loop, PING_TIMEOUT, ping_timeout,
t, NULL, NULL); t, g_direct_equal, NULL);
if (!active) { if (!active) {
active = TRUE; active = TRUE;