mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 23:58:25 +02:00
[xlib] Add locking around GC cache.
The per-screen cached of most-recently freed GCs lacks suitable locking for it to be threadsafe.
This commit is contained in:
parent
9166686abd
commit
dc714106e1
2 changed files with 22 additions and 10 deletions
|
|
@ -79,6 +79,7 @@ typedef struct _cairo_xlib_visual_info {
|
||||||
struct _cairo_xlib_screen_info {
|
struct _cairo_xlib_screen_info {
|
||||||
cairo_xlib_screen_info_t *next;
|
cairo_xlib_screen_info_t *next;
|
||||||
cairo_reference_count_t ref_count;
|
cairo_reference_count_t ref_count;
|
||||||
|
cairo_mutex_t mutex;
|
||||||
|
|
||||||
cairo_xlib_display_t *display;
|
cairo_xlib_display_t *display;
|
||||||
Screen *screen;
|
Screen *screen;
|
||||||
|
|
|
||||||
|
|
@ -256,12 +256,14 @@ _cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
CAIRO_MUTEX_LOCK (info->mutex);
|
||||||
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
|
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
|
||||||
if (info->gc[i] != NULL) {
|
if (info->gc[i] != NULL) {
|
||||||
XFreeGC (info->display->display, info->gc[i]);
|
XFreeGC (info->display->display, info->gc[i]);
|
||||||
info->gc[i] = NULL;
|
info->gc[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CAIRO_MUTEX_UNLOCK (info->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -295,6 +297,8 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
|
||||||
|
|
||||||
_cairo_array_fini (&info->visuals);
|
_cairo_array_fini (&info->visuals);
|
||||||
|
|
||||||
|
CAIRO_MUTEX_FINI (info->mutex);
|
||||||
|
|
||||||
free (info);
|
free (info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -335,6 +339,7 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
|
||||||
info = malloc (sizeof (cairo_xlib_screen_info_t));
|
info = malloc (sizeof (cairo_xlib_screen_info_t));
|
||||||
if (info != NULL) {
|
if (info != NULL) {
|
||||||
CAIRO_REFERENCE_COUNT_INIT (&info->ref_count, 2); /* Add one for display cache */
|
CAIRO_REFERENCE_COUNT_INIT (&info->ref_count, 2); /* Add one for display cache */
|
||||||
|
CAIRO_MUTEX_INIT (info->mutex);
|
||||||
info->display = _cairo_xlib_display_reference (display);
|
info->display = _cairo_xlib_display_reference (display);
|
||||||
info->screen = screen;
|
info->screen = screen;
|
||||||
info->has_render = FALSE;
|
info->has_render = FALSE;
|
||||||
|
|
@ -385,16 +390,18 @@ GC
|
||||||
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth)
|
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth)
|
||||||
{
|
{
|
||||||
GC gc;
|
GC gc;
|
||||||
|
cairo_bool_t needs_reset;
|
||||||
|
|
||||||
depth = depth_to_index (depth);
|
depth = depth_to_index (depth);
|
||||||
|
|
||||||
|
CAIRO_MUTEX_LOCK (info->mutex);
|
||||||
gc = info->gc[depth];
|
gc = info->gc[depth];
|
||||||
info->gc[depth] = NULL;
|
info->gc[depth] = NULL;
|
||||||
|
needs_reset = info->gc_needs_clip_reset & (1 << depth);
|
||||||
|
CAIRO_MUTEX_UNLOCK (info->mutex);
|
||||||
|
|
||||||
if (info->gc_needs_clip_reset & (1 << depth)) {
|
if (needs_reset)
|
||||||
XSetClipMask(info->display->display, gc, None);
|
XSetClipMask(info->display->display, gc, None);
|
||||||
info->gc_needs_clip_reset &= ~(1 << depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
return gc;
|
return gc;
|
||||||
}
|
}
|
||||||
|
|
@ -403,21 +410,25 @@ cairo_status_t
|
||||||
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip)
|
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip)
|
||||||
{
|
{
|
||||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||||
|
GC oldgc;
|
||||||
|
|
||||||
depth = depth_to_index (depth);
|
depth = depth_to_index (depth);
|
||||||
|
|
||||||
if (info->gc[depth] != NULL) {
|
CAIRO_MUTEX_LOCK (info->mutex);
|
||||||
status = _cairo_xlib_display_queue_work (info->display,
|
oldgc = info->gc[depth];
|
||||||
(cairo_xlib_notify_func) XFreeGC,
|
|
||||||
info->gc[depth],
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
info->gc[depth] = gc;
|
info->gc[depth] = gc;
|
||||||
if (reset_clip)
|
if (reset_clip)
|
||||||
info->gc_needs_clip_reset |= 1 << depth;
|
info->gc_needs_clip_reset |= 1 << depth;
|
||||||
else
|
else
|
||||||
info->gc_needs_clip_reset &= ~(1 << depth);
|
info->gc_needs_clip_reset &= ~(1 << depth);
|
||||||
|
CAIRO_MUTEX_UNLOCK (info->mutex);
|
||||||
|
|
||||||
|
if (oldgc != NULL) {
|
||||||
|
status = _cairo_xlib_display_queue_work (info->display,
|
||||||
|
(cairo_xlib_notify_func) XFreeGC,
|
||||||
|
oldgc,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue