summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.sources2
-rw-r--r--src/cairo-clip.c88
-rw-r--r--src/cairo-freed-pool-private.h121
-rw-r--r--src/cairo-freed-pool.c91
-rw-r--r--src/cairo-pattern.c115
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 ();
}