summaryrefslogtreecommitdiff
path: root/src/cairo-xlib-display.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2008-09-02 10:08:04 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2008-09-02 10:08:04 +0100
commit939b836bfa95df759aca96936bb9a6d89d3130b8 (patch)
tree48fea662e6672f40aa6215ec48522a4ca41baaee /src/cairo-xlib-display.c
parent38f779afcb84d48a1a146eec11a6db5c484d3578 (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.c90
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);