diff options
-rw-r--r-- | src/Makefile.sources | 2 | ||||
-rw-r--r-- | src/cairo-clip.c | 88 | ||||
-rw-r--r-- | src/cairo-freed-pool-private.h | 121 | ||||
-rw-r--r-- | src/cairo-freed-pool.c | 91 | ||||
-rw-r--r-- | src/cairo-pattern.c | 115 |
5 files changed, 234 insertions, 183 deletions
diff --git a/src/Makefile.sources b/src/Makefile.sources index 6dbe3fb0..197f346c 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -63,6 +63,7 @@ cairo_private = \ cairo-fixed-private.h \ cairo-fixed-type-private.h \ cairo-freelist-private.h \ + cairo-freed-pool-private.h \ cairo-gstate-private.h \ cairo-hash-private.h \ cairo-image-info-private.h \ @@ -116,6 +117,7 @@ cairo_sources = \ cairo-font-face-twin-data.c \ cairo-font-options.c \ cairo-freelist.c \ + cairo-freed-pool.c \ cairo-gstate.c \ cairo-hash.c \ cairo-hull.c \ diff --git a/src/cairo-clip.c b/src/cairo-clip.c index 2a50385f..b3d30341 100644 --- a/src/cairo-clip.c +++ b/src/cairo-clip.c @@ -42,95 +42,13 @@ #include "cairoint.h" #include "cairo-clip-private.h" #include "cairo-error-private.h" +#include "cairo-freed-pool-private.h" #include "cairo-path-fixed-private.h" #include "cairo-region-private.h" -/* Keep a stash of recently freed clip_paths, since we need to - * reallocate them frequently. - */ -#define MAX_FREED_POOL_SIZE 4 -typedef struct { - void *pool[MAX_FREED_POOL_SIZE]; - int top; -} freed_pool_t; - +#if HAS_FREED_POOL static freed_pool_t clip_path_pool; - -static void * -_atomic_fetch (void **slot) -{ - return _cairo_atomic_ptr_cmpxchg (slot, *slot, NULL); -} - -static cairo_bool_t -_atomic_store (void **slot, void *ptr) -{ - return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr) == NULL; -} - -static void * -_freed_pool_get (freed_pool_t *pool) -{ - void *ptr; - int i; - - i = pool->top - 1; - if (i < 0) - i = 0; - - ptr = _atomic_fetch (&pool->pool[i]); - if (ptr != NULL) { - pool->top = i; - return ptr; - } - - /* either empty or contended */ - for (i = ARRAY_LENGTH (pool->pool); i--;) { - ptr = _atomic_fetch (&pool->pool[i]); - if (ptr != NULL) { - pool->top = i; - return ptr; - } - } - - /* empty */ - pool->top = 0; - return NULL; -} - -static void -_freed_pool_put (freed_pool_t *pool, void *ptr) -{ - int i = pool->top; - - if (_atomic_store (&pool->pool[i], ptr)) { - pool->top = i + 1; - return; - } - - /* either full or contended */ - for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) { - if (_atomic_store (&pool->pool[i], ptr)) { - pool->top = i + 1; - return; - } - } - - /* full */ - pool->top = ARRAY_LENGTH (pool->pool); - free (ptr); -} - -static void -_freed_pool_reset (freed_pool_t *pool) -{ - int i; - - for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) { - free (pool->pool[i]); - pool->pool[i] = NULL; - } -} +#endif static cairo_clip_path_t * _cairo_clip_path_create (cairo_clip_t *clip) diff --git a/src/cairo-freed-pool-private.h b/src/cairo-freed-pool-private.h new file mode 100644 index 00000000..c8a69020 --- /dev/null +++ b/src/cairo-freed-pool-private.h @@ -0,0 +1,121 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2009 Chris Wilson + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is University of Southern + * California. + * + * Contributor(s): + * Chris Wilson <chris@chris-wilson.co.uk> + */ + +#ifndef CAIRO_FREED_POOL_H +#define CAIRO_FREED_POOL_H + +#include "cairoint.h" +#include "cairo-atomic-private.h" + +#if HAS_ATOMIC_OPS +/* Keep a stash of recently freed clip_paths, since we need to + * reallocate them frequently. + */ +#define MAX_FREED_POOL_SIZE 4 +typedef struct { + void *pool[MAX_FREED_POOL_SIZE]; + int top; +} freed_pool_t; + +static inline void * +_atomic_fetch (void **slot) +{ + return _cairo_atomic_ptr_cmpxchg (slot, *slot, NULL); +} + +static inline cairo_bool_t +_atomic_store (void **slot, void *ptr) +{ + return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr) == NULL; +} + +cairo_private void * +_freed_pool_get_search (freed_pool_t *pool); + +static inline void * +_freed_pool_get (freed_pool_t *pool) +{ + void *ptr; + int i; + + i = pool->top - 1; + if (i < 0) + i = 0; + + ptr = _atomic_fetch (&pool->pool[i]); + if (likely (ptr != NULL)) { + pool->top = i; + return ptr; + } + + /* either empty or contended */ + return _freed_pool_get_search (pool); +} + +cairo_private void +_freed_pool_put_search (freed_pool_t *pool, void *ptr); + +static inline void +_freed_pool_put (freed_pool_t *pool, void *ptr) +{ + int i; + + i = pool->top; + if (likely (_atomic_store (&pool->pool[i], ptr))) { + pool->top = i + 1; + return; + } + + /* either full or contended */ + _freed_pool_put_search (pool, ptr); +} + +cairo_private void +_freed_pool_reset (freed_pool_t *pool); + +#define HAS_FREED_POOL 1 + +#else + +typedef int freed_pool_t; + +#define _freed_pool_get(pool) NULL +#define _freed_pool_put(pool, ptr) free(ptr) +#define _freed_pool_reset(ptr) + +#endif + +#endif /* CAIRO_FREED_POOL_PRIVATE_H */ diff --git a/src/cairo-freed-pool.c b/src/cairo-freed-pool.c new file mode 100644 index 00000000..e225db44 --- /dev/null +++ b/src/cairo-freed-pool.c @@ -0,0 +1,91 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2009 Chris Wilson + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is University of Southern + * California. + * + * Contributor(s): + * Chris Wilson <chris@chris-wilson.co.uk> + */ + +#include "cairoint.h" + +#include "cairo-freed-pool-private.h" + +#if HAS_FREED_POOL + +void * +_freed_pool_get_search (freed_pool_t *pool) +{ + void *ptr; + int i; + + for (i = ARRAY_LENGTH (pool->pool); i--;) { + ptr = _atomic_fetch (&pool->pool[i]); + if (ptr != NULL) { + pool->top = i; + return ptr; + } + } + + /* empty */ + pool->top = 0; + return NULL; +} + +void +_freed_pool_put_search (freed_pool_t *pool, void *ptr) +{ + int i; + + for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) { + if (_atomic_store (&pool->pool[i], ptr)) { + pool->top = i + 1; + return; + } + } + + /* full */ + pool->top = ARRAY_LENGTH (pool->pool); + free (ptr); +} + +void +_freed_pool_reset (freed_pool_t *pool) +{ + int i; + + for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) { + free (pool->pool[i]); + pool->pool[i] = NULL; + } +} + +#endif diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index f5e5b9d1..00d6c077 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -30,6 +30,11 @@ #include "cairoint.h" #include "cairo-error-private.h" +#include "cairo-freed-pool-private.h" + +#if HAS_FREED_POOL +static freed_pool_t freed_pattern_pool[4]; +#endif static const cairo_solid_pattern_t _cairo_pattern_nil = { { CAIRO_PATTERN_TYPE_SOLID, /* type */ @@ -456,98 +461,6 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern, pattern->r2 = _cairo_fixed_from_double (fabs (radius1)); } -/* We use a small freed pattern cache here, because we don't want to - * constantly reallocate simple colors. */ -#define MAX_PATTERN_CACHE_SIZE 4 -typedef struct { - void *pool[MAX_PATTERN_CACHE_SIZE]; - int top; -} freed_pool_t; - -static freed_pool_t freed_pattern_pool[4]; - -static void * -_atomic_fetch (void **slot) -{ - return _cairo_atomic_ptr_cmpxchg (slot, *slot, NULL); -} - -static cairo_bool_t -_atomic_store (void **slot, void *pattern) -{ - return _cairo_atomic_ptr_cmpxchg (slot, NULL, pattern) == NULL; -} - -static void * -_freed_pattern_get (freed_pool_t *pool) -{ - cairo_pattern_t *pattern; - int i; - - i = pool->top - 1; - if (i < 0) - i = 0; - - pattern = _atomic_fetch (&pool->pool[i]); - if (likely (pattern != NULL)) { - pool->top = i; - return pattern; - } - - /* either empty or contended */ - for (i = ARRAY_LENGTH (pool->pool); i--;) { - pattern = _atomic_fetch (&pool->pool[i]); - if (pattern != NULL) { - pool->top = i; - return pattern; - } - } - - /* empty */ - pool->top = 0; - return NULL; -} - -static void -_freed_pattern_put (freed_pool_t *pool, - cairo_pattern_t *pattern) -{ - int i = pool->top; - - if (likely (i < ARRAY_LENGTH (pool->pool) && - _atomic_store (&pool->pool[i], pattern))) - { - pool->top = i + 1; - return; - } - - /* either full or contended */ - for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) { - if (_atomic_store (&pool->pool[i], pattern)) { - pool->top = i + 1; - return; - } - } - - /* full */ - pool->top = ARRAY_LENGTH (pool->pool); - free (pattern); -} - -static void -_freed_patterns_reset (void) -{ - int i, j; - - for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++) { - freed_pool_t *pool = &freed_pattern_pool[i]; - for (j = 0; j < ARRAY_LENGTH (pool->pool); j++) { - free (pool->pool[j]); - pool->pool[j] = NULL; - } - } -} - cairo_pattern_t * _cairo_pattern_create_solid (const cairo_color_t *color, cairo_content_t content) @@ -555,7 +468,7 @@ _cairo_pattern_create_solid (const cairo_color_t *color, cairo_solid_pattern_t *pattern; pattern = - _freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]); + _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]); if (unlikely (pattern == NULL)) { /* None cached, need to create a new pattern. */ pattern = malloc (sizeof (cairo_solid_pattern_t)); @@ -694,7 +607,7 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface) return _cairo_pattern_create_in_error (surface->status); pattern = - _freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]); + _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]); if (unlikely (pattern == NULL)) { pattern = malloc (sizeof (cairo_surface_pattern_t)); if (unlikely (pattern == NULL)) { @@ -744,7 +657,7 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1) cairo_linear_pattern_t *pattern; pattern = - _freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]); + _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]); if (unlikely (pattern == NULL)) { pattern = malloc (sizeof (cairo_linear_pattern_t)); if (unlikely (pattern == NULL)) { @@ -796,7 +709,7 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0, cairo_radial_pattern_t *pattern; pattern = - _freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]); + _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]); if (unlikely (pattern == NULL)) { pattern = malloc (sizeof (cairo_radial_pattern_t)); if (unlikely (pattern == NULL)) { @@ -900,7 +813,7 @@ cairo_pattern_destroy (cairo_pattern_t *pattern) _cairo_pattern_fini (pattern); /* maintain a small cache of freed patterns */ - _freed_pattern_put (&freed_pattern_pool[type], pattern); + _freed_pool_put (&freed_pattern_pool[type], pattern); } slim_hidden_def (cairo_pattern_destroy); @@ -3135,6 +3048,12 @@ cairo_pattern_get_radial_circles (cairo_pattern_t *pattern, void _cairo_pattern_reset_static_data (void) { - _freed_patterns_reset (); +#if HAS_FREED_POOL + int i; + + for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++) + _freed_pool_reset (&freed_pattern_pool[i]); +#endif + _cairo_pattern_reset_solid_surface_cache (); } |