summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrea Canciani <ranma42@gmail.com>2011-06-25 15:35:48 +0200
committerAndrea Canciani <ranma42@gmail.com>2011-06-25 15:35:48 +0200
commitf46ba56d5b8c54be5f0379aca204c0ce05d0f58a (patch)
tree874fc27b2202a329a3f3f07d9924485ee0557ba4
parenta6d4d840d324de55a973663e5a416751619dc490 (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.h15
-rw-r--r--src/cairo.c94
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);