diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2008-09-02 10:08:04 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2008-09-02 10:08:04 +0100 |
commit | 939b836bfa95df759aca96936bb9a6d89d3130b8 (patch) | |
tree | 48fea662e6672f40aa6215ec48522a4ca41baaee /src/cairo-xlib-display.c | |
parent | 38f779afcb84d48a1a146eec11a6db5c484d3578 (diff) |
[xlib] Use an embedded doubly-linked list for the close display hooks.
Kill the allocation and linear search of the close display list on remove,
by embedding a list node into the parent structure.
Original patch by Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation.
https://bugzilla.mozilla.org/show_bug.cgi?id=453199#c5
Diffstat (limited to 'src/cairo-xlib-display.c')
-rw-r--r-- | src/cairo-xlib-display.c | 90 |
1 files changed, 41 insertions, 49 deletions
diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c index 895258d3..ff2e08ed 100644 --- a/src/cairo-xlib-display.c +++ b/src/cairo-xlib-display.c @@ -29,6 +29,8 @@ * * The Initial Developer of the Original Code is Chris Wilson. * + * Contributor(s): + * Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation */ #include "cairoint.h" @@ -65,10 +67,14 @@ struct _cairo_xlib_job { static cairo_xlib_display_t *_cairo_xlib_display_list; static void +_cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display, + cairo_xlib_hook_t *hook); + +static void _cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display) { cairo_xlib_screen_info_t *screen; - cairo_xlib_hook_t *hooks, *list; + cairo_xlib_hook_t *hook; /* call all registered shutdown routines */ CAIRO_MUTEX_LOCK (display->mutex); @@ -76,28 +82,16 @@ _cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display) for (screen = display->screens; screen != NULL; screen = screen->next) _cairo_xlib_screen_info_close_display (screen); - hooks = display->close_display_hooks; - while (hooks != NULL) { - display->close_display_hooks = NULL; - CAIRO_MUTEX_UNLOCK (display->mutex); - - list = hooks; - do { - cairo_xlib_hook_t *hook = list; - list = hook->next; + while (TRUE) { + hook = display->close_display_hooks; + if (hook == NULL) + break; - hook->func (display->display, hook->data); - } while (list != NULL); + _cairo_xlib_remove_close_display_hook_internal (display, hook); + CAIRO_MUTEX_UNLOCK (display->mutex); + hook->func (display->display, hook); CAIRO_MUTEX_LOCK (display->mutex); - do { - cairo_xlib_hook_t *hook = hooks; - hooks = hook->next; - - _cairo_freelist_free (&display->hook_freelist, hook); - } while (hooks != NULL); - - hooks = display->close_display_hooks; } display->closed = TRUE; @@ -151,7 +145,6 @@ _cairo_xlib_display_destroy (cairo_xlib_display_t *display) _cairo_freelist_free (&display->wq_freelist, job); } _cairo_freelist_fini (&display->wq_freelist); - _cairo_freelist_fini (&display->hook_freelist); CAIRO_MUTEX_FINI (display->mutex); @@ -277,7 +270,6 @@ _cairo_xlib_display_get (Display *dpy) XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display); _cairo_freelist_init (&display->wq_freelist, sizeof (cairo_xlib_job_t)); - _cairo_freelist_init (&display->hook_freelist, sizeof (cairo_xlib_hook_t)); CAIRO_REFERENCE_COUNT_INIT (&display->ref_count, 2); /* add one for the CloseDisplay */ CAIRO_MUTEX_INIT (display->mutex); @@ -326,56 +318,56 @@ UNLOCK: } cairo_bool_t -_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data) +_cairo_xlib_add_close_display_hook (Display *dpy, cairo_xlib_hook_t *hook) { cairo_xlib_display_t *display; - cairo_xlib_hook_t *hook; - cairo_bool_t ret = FALSE; display = _cairo_xlib_display_get (dpy); if (display == NULL) return FALSE; CAIRO_MUTEX_LOCK (display->mutex); - if (display->closed == FALSE) { - hook = _cairo_freelist_alloc (&display->hook_freelist); - if (hook != NULL) { - hook->func = func; - hook->data = data; - - hook->next = display->close_display_hooks; - display->close_display_hooks = hook; - ret = TRUE; - } - } + hook->prev = NULL; + hook->next = display->close_display_hooks; + if (hook->next != NULL) + hook->next->prev = hook; + display->close_display_hooks = hook; CAIRO_MUTEX_UNLOCK (display->mutex); _cairo_xlib_display_destroy (display); - return ret; + return TRUE; +} + +/* display->mutex must be held */ +static void +_cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display, + cairo_xlib_hook_t *hook) +{ + if (display->close_display_hooks == hook) + display->close_display_hooks = hook->next; + else if (hook->prev != NULL) + hook->prev->next = hook->next; + + if (hook->next != NULL) + hook->next->prev = hook->prev; + + hook->prev = NULL; + hook->next = NULL; } void -_cairo_xlib_remove_close_display_hooks (Display *dpy, const void *data) +_cairo_xlib_remove_close_display_hook (Display *dpy, + cairo_xlib_hook_t *hook) { cairo_xlib_display_t *display; - cairo_xlib_hook_t *hook, *next, **prev; display = _cairo_xlib_display_get (dpy); if (display == NULL) return; CAIRO_MUTEX_LOCK (display->mutex); - prev = &display->close_display_hooks; - for (hook = display->close_display_hooks; hook != NULL; hook = next) { - next = hook->next; - if (hook->data == data) { - *prev = hook->next; - _cairo_freelist_free (&display->hook_freelist, hook); - break; - } - prev = &hook->next; - } + _cairo_xlib_remove_close_display_hook_internal (display, hook); CAIRO_MUTEX_UNLOCK (display->mutex); _cairo_xlib_display_destroy (display); |