2007-08-08 Emmanuele Bassi <ebassi@openedhand.com>

* clutter/clutter-timeout-pool.c: Fix sorting of the pool
	when inserting and removing timeout sources. (#449, Neil
	Roberts)
This commit is contained in:
Emmanuele Bassi 2007-08-08 21:36:16 +00:00
parent 705f47783a
commit fae203c1ea
2 changed files with 77 additions and 12 deletions

View File

@ -1,3 +1,9 @@
2007-08-08 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-timeout-pool.c: Fix sorting of the pool
when inserting and removing timeout sources. (#449, Neil
Roberts)
2007-08-08 Emmanuele Bassi <ebassi@openedhand.com> 2007-08-08 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-main.c (clutter_get_timestamp): Remove * clutter/clutter-main.c (clutter_get_timestamp): Remove

View File

@ -93,10 +93,11 @@ clutter_timeout_sort (gconstpointer a,
{ {
const ClutterTimeout *t_a = a; const ClutterTimeout *t_a = a;
const ClutterTimeout *t_b = b; const ClutterTimeout *t_b = b;
gint comparison;
return ((t_a->expiration.tv_sec < t_b->expiration.tv_sec) || return ((comparison = t_a->expiration.tv_sec - t_b->expiration.tv_sec)
((t_a->expiration.tv_sec == t_b->expiration.tv_sec) && ? comparison
(t_a->expiration.tv_usec <= t_b->expiration.tv_usec))); : t_a->expiration.tv_usec - t_b->expiration.tv_usec);
} }
static gint static gint
@ -283,6 +284,47 @@ clutter_timeout_pool_check (GSource *source)
return (pool->ready > 0); return (pool->ready > 0);
} }
static GList *
clutter_timeout_pool_insert_sorted (GList *node, GList *list)
{
GList *l, *last = NULL, *next;
/* Find the first timeout which expires after this one */
for (l = list; l; l = l->next)
{
ClutterTimeout *t_a = node->data;
ClutterTimeout *t_b = l->data;
last = l;
next = l->next;
if (clutter_timeout_sort (t_a, t_b) < 0)
break;
}
/* If we didn't find an entry then add it at the end */
if (!l)
{
node->prev = last;
node->next = NULL;
if (last)
last->next = node;
}
else
{
/* Otherwise insert it before the found entry */
node->next = l;
node->prev = l->prev;
l->prev = node;
if (node->prev)
node->prev->next = node;
}
return node->prev ? list : node;
}
static gboolean static gboolean
clutter_timeout_pool_dispatch (GSource *source, clutter_timeout_pool_dispatch (GSource *source,
GSourceFunc func, GSourceFunc func,
@ -290,7 +332,10 @@ clutter_timeout_pool_dispatch (GSource *source,
{ {
ClutterTimeoutPool *pool = (ClutterTimeoutPool *) source; ClutterTimeoutPool *pool = (ClutterTimeoutPool *) source;
GList *l = pool->timeouts; GList *l = pool->timeouts;
gboolean sort_needed = FALSE; GList *dispatched = NULL;
GList *n, *next;
clutter_threads_enter ();
/* the main loop might have predicted this, so we repeat the /* the main loop might have predicted this, so we repeat the
* check for ready timeouts. * check for ready timeouts.
@ -301,16 +346,13 @@ clutter_timeout_pool_dispatch (GSource *source,
while (l && l->data && (pool->ready-- > 0)) while (l && l->data && (pool->ready-- > 0))
{ {
ClutterTimeout *timeout = l->data; ClutterTimeout *timeout = l->data;
GList *next = l->next;
gboolean needs_removing = FALSE; gboolean needs_removing = FALSE;
next = l->next;
timeout->flags &= ~CLUTTER_TIMEOUT_READY; timeout->flags &= ~CLUTTER_TIMEOUT_READY;
if (!TIMEOUT_REMOVED (timeout)) if (!TIMEOUT_REMOVED (timeout))
{
needs_removing = !clutter_timeout_dispatch (source, timeout); needs_removing = !clutter_timeout_dispatch (source, timeout);
sort_needed = needs_removing;
}
else else
needs_removing = TRUE; needs_removing = TRUE;
@ -321,15 +363,32 @@ clutter_timeout_pool_dispatch (GSource *source,
clutter_timeout_free (timeout); clutter_timeout_free (timeout);
g_list_free1 (l); g_list_free1 (l);
} }
else
{
/* Move the list node to a singly-linked list of dispatched
timeouts */
if (next)
next->prev = NULL;
l->next = dispatched;
dispatched = l;
}
l = next; l = next;
} }
if (sort_needed) /* Re-insert the dispatched timeouts in sorted order */
pool->timeouts = g_list_sort (pool->timeouts, clutter_timeout_sort); for (n = dispatched; n; n = next)
{
next = n->next;
l = clutter_timeout_pool_insert_sorted (n, l);
}
pool->timeouts = l;
pool->ready = 0; pool->ready = 0;
clutter_threads_leave ();
return TRUE; return TRUE;
} }