diff options
author | Andrea Canciani <ranma42@gmail.com> | 2011-06-25 15:35:48 +0200 |
---|---|---|
committer | Andrea Canciani <ranma42@gmail.com> | 2011-06-25 15:35:48 +0200 |
commit | f46ba56d5b8c54be5f0379aca204c0ce05d0f58a (patch) | |
tree | 874fc27b2202a329a3f3f07d9924485ee0557ba4 | |
parent | a6d4d840d324de55a973663e5a416751619dc490 (diff) |
Do not open-code freed-pool
Reuse the freed-pool system to reduce allocation pressure of context
creation/destruction.
As a side effect, this removes the use of ffs() on Win32, cleaning up
some MSVC-specific code and fixing a mingw-related build issue.
Fixes https://bugs.freedesktop.org/show_bug.cgi?id=30277
-rw-r--r-- | src/cairo-compiler-private.h | 15 | ||||
-rw-r--r-- | src/cairo.c | 94 |
2 files changed, 12 insertions, 97 deletions
diff --git a/src/cairo-compiler-private.h b/src/cairo-compiler-private.h index 2bbd3025..96034d6e 100644 --- a/src/cairo-compiler-private.h +++ b/src/cairo-compiler-private.h @@ -219,21 +219,6 @@ #ifdef _MSC_VER #undef inline #define inline __inline - -/* Add a definition of ffs */ -#include <intrin.h> -#pragma intrinsic(_BitScanForward) -static __forceinline int -ffs (int x) -{ - unsigned long i; - - if (_BitScanForward(&i, x) != 0) - return i + 1; - - return 0; -} - #endif #if defined(_MSC_VER) && defined(_M_IX86) diff --git a/src/cairo.c b/src/cairo.c index dde9dacd..42afe26a 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -41,6 +41,7 @@ #include "cairo-arc-private.h" #include "cairo-error-private.h" +#include "cairo-freed-pool-private.h" #include "cairo-path-private.h" /** @@ -177,85 +178,11 @@ _cairo_set_error (cairo_t *cr, cairo_status_t status) _cairo_status_set_error (&cr->status, _cairo_error (status)); } -/* We keep a small stash of contexts to reduce malloc pressure */ -#define CAIRO_STASH_SIZE 4 -#if CAIRO_NO_MUTEX -static struct { - cairo_t pool[CAIRO_STASH_SIZE]; - int occupied; -} _context_stash; - -static cairo_t * -_context_get (void) -{ - int avail; - - avail = ffs (~_context_stash.occupied) - 1; - if (avail >= CAIRO_STASH_SIZE) - return malloc (sizeof (cairo_t)); - - _context_stash.occupied |= 1 << avail; - return &_context_stash.pool[avail]; -} - -static void -_context_put (cairo_t *cr) -{ - if (cr < &_context_stash.pool[0] || - cr >= &_context_stash.pool[CAIRO_STASH_SIZE]) - { - free (cr); - return; - } - - _context_stash.occupied &= ~(1 << (cr - &_context_stash.pool[0])); -} -#elif HAS_ATOMIC_OPS -static struct { - cairo_t pool[CAIRO_STASH_SIZE]; - cairo_atomic_int_t occupied; -} _context_stash; - -static cairo_t * -_context_get (void) -{ - cairo_atomic_int_t avail, old, new; - - do { - old = _cairo_atomic_int_get (&_context_stash.occupied); - avail = ffs (~old) - 1; - if (avail >= CAIRO_STASH_SIZE) - return malloc (sizeof (cairo_t)); - - new = old | (1 << avail); - } while (! _cairo_atomic_int_cmpxchg (&_context_stash.occupied, old, new)); - - return &_context_stash.pool[avail]; -} - -static void -_context_put (cairo_t *cr) -{ - cairo_atomic_int_t old, new, avail; - - if (cr < &_context_stash.pool[0] || - cr >= &_context_stash.pool[CAIRO_STASH_SIZE]) - { - free (cr); - return; - } - - avail = ~(1 << (cr - &_context_stash.pool[0])); - do { - old = _cairo_atomic_int_get (&_context_stash.occupied); - new = old & avail; - } while (! _cairo_atomic_int_cmpxchg (&_context_stash.occupied, old, new)); -} -#else -#define _context_get() malloc (sizeof (cairo_t)) -#define _context_put(cr) free (cr) +#if HAS_FREED_POOL +static freed_pool_t context_pool; #endif + /* XXX This should disappear in favour of a common pool of error objects. */ static cairo_t *_cairo_nil__objects[CAIRO_STATUS_LAST_STATUS + 1]; @@ -346,9 +273,12 @@ cairo_create (cairo_surface_t *target) if (unlikely (target->status)) return _cairo_create_in_error (target->status); - cr = _context_get (); - if (unlikely (cr == NULL)) - return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + cr = _freed_pool_get (&context_pool); + if (unlikely (cr == NULL)) { + cr = malloc (sizeof (cairo_t)); + if (unlikely (cr == NULL)) + return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + } CAIRO_REFERENCE_COUNT_INIT (&cr->ref_count, 1); @@ -363,7 +293,7 @@ cairo_create (cairo_surface_t *target) status = _cairo_gstate_init (cr->gstate, target); if (unlikely (status)) { - _context_put (cr); + _freed_pool_put (&context_pool, cr); cr = _cairo_create_in_error (status); } @@ -436,7 +366,7 @@ cairo_destroy (cairo_t *cr) /* mark the context as invalid to protect against misuse */ cr->status = CAIRO_STATUS_NULL_POINTER; - _context_put (cr); + _freed_pool_put (&context_pool, cr); } slim_hidden_def (cairo_destroy); |