[cairo-atomic] Rewrite reference counting using atomic ops.

Introduce an opaque cairo_reference_count_t and define operations on it
in terms of atomic ops. Update all users of reference counters to use
the new opaque type.
This commit is contained in:
Chris Wilson 2007-09-23 21:08:09 +01:00
parent 8b6c871c90
commit 03be41151d
18 changed files with 242 additions and 175 deletions

View file

@ -209,6 +209,7 @@ libcairo_la_base_sources = \
cairo-pen.c \
cairo-polygon.c \
cairo-rectangle.c \
cairo-reference-count-private.h \
cairo-region.c \
cairo-scaled-font.c \
cairo-scaled-font-private.h \

View file

@ -42,12 +42,12 @@
extern const cairo_private cairo_rectangle_list_t _cairo_rectangles_nil;
struct _cairo_clip_path {
unsigned int ref_count;
cairo_path_fixed_t path;
cairo_fill_rule_t fill_rule;
double tolerance;
cairo_antialias_t antialias;
cairo_clip_path_t *prev;
cairo_reference_count_t ref_count;
cairo_path_fixed_t path;
cairo_fill_rule_t fill_rule;
double tolerance;
cairo_antialias_t antialias;
cairo_clip_path_t *prev;
};
struct _cairo_clip {

View file

@ -285,7 +285,7 @@ _cairo_clip_intersect_path (cairo_clip_t *clip,
return status;
}
clip_path->ref_count = 1;
CAIRO_REFERENCE_COUNT_INIT (&clip_path->ref_count, 1);
clip_path->fill_rule = fill_rule;
clip_path->tolerance = tolerance;
clip_path->antialias = antialias;
@ -301,7 +301,9 @@ _cairo_clip_path_reference (cairo_clip_path_t *clip_path)
if (clip_path == NULL)
return NULL;
clip_path->ref_count++;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count));
_cairo_reference_count_inc (&clip_path->ref_count);
return clip_path;
}
@ -312,8 +314,9 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
if (clip_path == NULL)
return;
clip_path->ref_count--;
if (clip_path->ref_count)
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count));
if (! _cairo_reference_count_dec_and_test (&clip_path->ref_count))
return;
_cairo_path_fixed_fini (&clip_path->path);

View file

@ -50,7 +50,7 @@ static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
const cairo_font_face_t _cairo_font_face_nil = {
{ 0 }, /* hash_entry */
CAIRO_STATUS_NO_MEMORY, /* status */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
{ 0, 0, 0, NULL }, /* user_data */
&_cairo_toy_font_face_backend
};
@ -62,7 +62,7 @@ _cairo_font_face_init (cairo_font_face_t *font_face,
CAIRO_MUTEX_INITIALIZE ();
font_face->status = CAIRO_STATUS_SUCCESS;
font_face->ref_count = 1;
CAIRO_REFERENCE_COUNT_INIT (&font_face->ref_count, 1);
font_face->backend = backend;
_cairo_user_data_array_init (&font_face->user_data);
@ -85,18 +85,15 @@ _cairo_font_face_init (cairo_font_face_t *font_face,
cairo_font_face_t *
cairo_font_face_reference (cairo_font_face_t *font_face)
{
if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
if (font_face == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return font_face;
CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
/* We would normally assert (font_face->ref_count >0) here but we
/* We would normally assert that we have a reference here but we
* can't get away with that due to the zombie case as documented
* in _cairo_ft_font_face_destroy. */
font_face->ref_count++;
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
_cairo_reference_count_inc (&font_face->ref_count);
return font_face;
}
@ -113,19 +110,14 @@ slim_hidden_def (cairo_font_face_reference);
void
cairo_font_face_destroy (cairo_font_face_t *font_face)
{
if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
if (font_face == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return;
CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count));
assert (font_face->ref_count > 0);
if (--(font_face->ref_count) > 0) {
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
if (! _cairo_reference_count_dec_and_test (&font_face->ref_count))
return;
}
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
font_face->backend->destroy (font_face);
@ -133,7 +125,7 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
* FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
* need to effectively mutually reference each other
*/
if (font_face->ref_count > 0)
if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count))
return;
_cairo_user_data_array_fini (&font_face->user_data);
@ -173,10 +165,11 @@ cairo_font_face_get_type (cairo_font_face_t *font_face)
unsigned int
cairo_font_face_get_reference_count (cairo_font_face_t *font_face)
{
if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
if (font_face == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return 0;
return font_face->ref_count;
return CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->ref_count);
}
/**
@ -237,7 +230,7 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
void *user_data,
cairo_destroy_func_t destroy)
{
if (font_face->ref_count == CAIRO_REF_COUNT_INVALID)
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return CAIRO_STATUS_NO_MEMORY;
return _cairo_user_data_array_set_data (&font_face->user_data,
@ -395,7 +388,7 @@ _cairo_toy_font_face_create (const char *family,
{
/* We increment the reference count here manually to avoid
double-locking. */
font_face->base.ref_count++;
_cairo_reference_count_inc (&font_face->base.ref_count);
_cairo_toy_font_face_hash_table_unlock ();
return &font_face->base;
}
@ -475,7 +468,7 @@ void
_cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font,
const cairo_unscaled_font_backend_t *backend)
{
unscaled_font->ref_count = 1;
CAIRO_REFERENCE_COUNT_INIT (&unscaled_font->ref_count, 1);
unscaled_font->backend = backend;
}
@ -485,7 +478,9 @@ _cairo_unscaled_font_reference (cairo_unscaled_font_t *unscaled_font)
if (unscaled_font == NULL)
return NULL;
unscaled_font->ref_count++;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count));
_cairo_reference_count_inc (&unscaled_font->ref_count);
return unscaled_font;
}
@ -496,7 +491,9 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
if (unscaled_font == NULL)
return;
if (--(unscaled_font->ref_count) > 0)
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count));
if (! _cairo_reference_count_dec_and_test (&unscaled_font->ref_count))
return;
unscaled_font->backend->destroy (unscaled_font);

View file

@ -2198,7 +2198,7 @@ _cairo_ft_font_face_destroy (void *abstract_face)
if (font_face->unscaled &&
font_face->unscaled->from_face &&
font_face->unscaled->base.ref_count > 1)
CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1)
{
cairo_font_face_reference (&font_face->base);

View file

@ -42,7 +42,7 @@ static const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
&cairo_image_surface_backend, /* backend */
CAIRO_SURFACE_TYPE_IMAGE,
CAIRO_CONTENT_COLOR,
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_INVALID_FORMAT, /* status */
FALSE, /* finished */
{ 0, /* size */

View file

@ -32,31 +32,31 @@
const cairo_solid_pattern_t _cairo_pattern_nil = {
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_NO_MEMORY, /* status */
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_NO_MEMORY, /* status */
{ 0, 0, 0, NULL }, /* user_data */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
};
static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_NULL_POINTER,/* status */
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_NULL_POINTER, /* status */
{ 0, 0, 0, NULL }, /* user_data */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
};
const cairo_solid_pattern_t cairo_pattern_none = {
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_SUCCESS, /* status */
{ 0, 0, 0, NULL }, /* user_data */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
};
@ -95,7 +95,7 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
CAIRO_MUTEX_INITIALIZE ();
pattern->type = type;
pattern->ref_count = 1;
CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
pattern->status = CAIRO_STATUS_SUCCESS;
_cairo_user_data_array_init (&pattern->user_data);
@ -186,7 +186,7 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern,
}
/* The reference count and user_data array are unique to the copy. */
pattern->ref_count = 1;
CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
_cairo_user_data_array_init (&pattern->user_data);
return CAIRO_STATUS_SUCCESS;
@ -577,12 +577,13 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
cairo_pattern_t *
cairo_pattern_reference (cairo_pattern_t *pattern)
{
if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID)
if (pattern == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
return pattern;
assert (pattern->ref_count > 0);
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
pattern->ref_count++;
_cairo_reference_count_inc (&pattern->ref_count);
return pattern;
}
@ -634,13 +635,13 @@ slim_hidden_def (cairo_pattern_status);
void
cairo_pattern_destroy (cairo_pattern_t *pattern)
{
if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID)
if (pattern == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
return;
assert (pattern->ref_count > 0);
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
pattern->ref_count--;
if (pattern->ref_count)
if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
return;
_cairo_pattern_fini (pattern);
@ -680,10 +681,11 @@ slim_hidden_def (cairo_pattern_destroy);
unsigned int
cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
{
if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID)
if (pattern == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
return 0;
return pattern->ref_count;
return CAIRO_REFERENCE_COUNT_GET_VALUE (&pattern->ref_count);
}
/**
@ -732,7 +734,7 @@ cairo_pattern_set_user_data (cairo_pattern_t *pattern,
void *user_data,
cairo_destroy_func_t destroy)
{
if (pattern->ref_count == CAIRO_REF_COUNT_INVALID)
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
return CAIRO_STATUS_NO_MEMORY;
return _cairo_user_data_array_set_data (&pattern->user_data,
@ -1328,7 +1330,7 @@ _cairo_pattern_solid_surface_matches (
const cairo_solid_pattern_t *pattern,
cairo_surface_t *dst)
{
if (cache->surface->ref_count != 1)
if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
return FALSE;
if (! _cairo_color_equal (&cache->color, &pattern->color))

View file

@ -36,11 +36,12 @@
#ifndef CAIRO_PRIVATE_H
#define CAIRO_PRIVATE_H
#include "cairo-reference-count-private.h"
#include "cairo-gstate-private.h"
#include "cairo-path-fixed-private.h"
struct _cairo {
unsigned int ref_count;
cairo_reference_count_t ref_count;
cairo_status_t status;

View file

@ -0,0 +1,66 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2007 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_REFRENCE_COUNT_PRIVATE_H
#define CAIRO_REFRENCE_COUNT_PRIVATE_H
#include "cairo-atomic-private.h"
CAIRO_BEGIN_DECLS
/* Encapsulate operations on the object's reference count */
typedef struct {
cairo_atomic_int_t ref_count;
} cairo_reference_count_t;
#define _cairo_reference_count_inc(RC) _cairo_atomic_int_inc (&(RC)->ref_count)
#define _cairo_reference_count_dec_and_test(RC) _cairo_atomic_int_dec_and_test (&(RC)->ref_count)
#define CAIRO_REFERENCE_COUNT_INIT(RC, VALUE) ((RC)->ref_count = (VALUE))
#define CAIRO_REFERENCE_COUNT_GET_VALUE(RC) _cairo_atomic_int_get (&(RC)->ref_count)
#define CAIRO_REFERENCE_COUNT_SET_VALUE(RC, VALUE) _cairo_atomic_int_set (&(RC)->ref_count, (VALUE))
#define CAIRO_REFERENCE_COUNT_INVALID_VALUE ((cairo_atomic_int_t) -1)
#define CAIRO_REFERENCE_COUNT_INVALID ((cairo_reference_count_t) {CAIRO_REFERENCE_COUNT_INVALID_VALUE})
#define CAIRO_REFERENCE_COUNT_IS_INVALID(RC) (CAIRO_REFERENCE_COUNT_GET_VALUE (RC) == CAIRO_REFERENCE_COUNT_INVALID_VALUE)
#define CAIRO_REFERENCE_COUNT_HAS_REFERENCE(RC) (CAIRO_REFERENCE_COUNT_GET_VALUE (RC) > 0)
CAIRO_END_DECLS
#endif

View file

@ -42,6 +42,7 @@
#include "cairo-types-private.h"
#include "cairo-mutex-type-private.h"
#include "cairo-reference-count-private.h"
struct _cairo_scaled_font {
/* For most cairo objects, the rule for multiple threads is that
@ -79,7 +80,7 @@ struct _cairo_scaled_font {
/* useful bits for _cairo_scaled_font_nil */
cairo_status_t status;
unsigned int ref_count;
cairo_reference_count_t ref_count;
cairo_user_data_array_t user_data;
/* hash key members */

View file

@ -180,7 +180,7 @@ _cairo_scaled_glyph_destroy (void *abstract_glyph)
const cairo_scaled_font_t _cairo_scaled_font_nil = {
{ 0 }, /* hash_entry */
CAIRO_STATUS_NO_MEMORY, /* status */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
{ 0, 0, 0, NULL }, /* user_data */
NULL, /* font_face */
{ 1., 0., 0., 1., 0, 0}, /* font_matrix */
@ -241,7 +241,7 @@ _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
cairo_font_type_t
cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font)
{
if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
return CAIRO_FONT_TYPE_TOY;
return scaled_font->backend->type;
@ -352,7 +352,7 @@ _cairo_scaled_font_map_destroy (void)
/* We should only get here through the reset_static_data path
* and there had better not be any active references at that
* point. */
assert (scaled_font->ref_count == 0);
assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
_cairo_hash_table_remove (font_map->hash_table,
&scaled_font->hash_entry);
_cairo_scaled_font_fini (scaled_font);
@ -483,7 +483,7 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
if (scaled_font->glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
scaled_font->ref_count = 1;
CAIRO_REFERENCE_COUNT_INIT (&scaled_font->ref_count, 1);
_cairo_user_data_array_init (&scaled_font->user_data);
@ -613,7 +613,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
* been found in font_map->holdovers, (which means this caching is
* actually working). So now we remove it from the holdovers
* array. */
if (scaled_font->ref_count == 0) {
if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)) {
int i;
for (i = 0; i < font_map->num_holdovers; i++)
@ -635,7 +635,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
* than calling into cairo_scaled_font_reference), since we
* must modify the reference count while our lock is still
* held. */
scaled_font->ref_count++;
_cairo_reference_count_inc (&scaled_font->ref_count);
_cairo_scaled_font_map_unlock ();
return scaled_font;
}
@ -686,16 +686,13 @@ slim_hidden_def (cairo_scaled_font_create);
cairo_scaled_font_t *
cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
{
if (scaled_font == NULL || scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
if (scaled_font == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
return scaled_font;
_cairo_scaled_font_map_lock ();
{
assert (scaled_font->ref_count > 0);
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
scaled_font->ref_count++;
}
_cairo_scaled_font_map_unlock ();
_cairo_reference_count_inc (&scaled_font->ref_count);
return scaled_font;
}
@ -715,38 +712,37 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
cairo_scaled_font_map_t *font_map;
cairo_scaled_font_t *lru = NULL;
if (scaled_font == NULL || scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
if (scaled_font == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
return;
font_map = _cairo_scaled_font_map_lock ();
{
assert (font_map != NULL);
assert (font_map != NULL);
assert (scaled_font->ref_count > 0);
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
if (--(scaled_font->ref_count) == 0)
if (_cairo_reference_count_dec_and_test (&scaled_font->ref_count)) {
/* Rather than immediately destroying this object, we put it into
* the font_map->holdovers array in case it will get used again
* soon (and is why we must hold the lock over the atomic op on
* the reference count). To make room for it, we do actually
* destroy the least-recently-used holdover.
*/
if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS)
{
/* Rather than immediately destroying this object, we put it into
* the font_map->holdovers array in case it will get used again
* soon. To make room for it, we do actually destroy the
* least-recently-used holdover.
*/
if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS)
{
lru = font_map->holdovers[0];
assert (lru->ref_count == 0);
lru = font_map->holdovers[0];
assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&lru->ref_count));
_cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry);
_cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry);
font_map->num_holdovers--;
memmove (&font_map->holdovers[0],
&font_map->holdovers[1],
font_map->num_holdovers * sizeof (cairo_scaled_font_t*));
}
font_map->holdovers[font_map->num_holdovers] = scaled_font;
font_map->num_holdovers++;
font_map->num_holdovers--;
memmove (&font_map->holdovers[0],
&font_map->holdovers[1],
font_map->num_holdovers * sizeof (cairo_scaled_font_t*));
}
font_map->holdovers[font_map->num_holdovers] = scaled_font;
font_map->num_holdovers++;
}
_cairo_scaled_font_map_unlock ();
@ -777,10 +773,11 @@ slim_hidden_def (cairo_scaled_font_destroy);
unsigned int
cairo_scaled_font_get_reference_count (cairo_scaled_font_t *scaled_font)
{
if (scaled_font == NULL || scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
if (scaled_font == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
return 0;
return scaled_font->ref_count;
return CAIRO_REFERENCE_COUNT_GET_VALUE (&scaled_font->ref_count);
}
/**
@ -829,7 +826,7 @@ cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font,
void *user_data,
cairo_destroy_func_t destroy)
{
if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
return CAIRO_STATUS_NO_MEMORY;
return _cairo_user_data_array_set_data (&scaled_font->user_data,

View file

@ -41,6 +41,7 @@
#include "cairo.h"
#include "cairo-types-private.h"
#include "cairo-reference-count-private.h"
struct _cairo_surface {
const cairo_surface_backend_t *backend;
@ -52,7 +53,7 @@ struct _cairo_surface {
cairo_content_t content;
unsigned int ref_count;
cairo_reference_count_t ref_count;
cairo_status_t status;
cairo_bool_t finished;
cairo_user_data_array_t user_data;

View file

@ -46,7 +46,7 @@ const cairo_surface_t name = { \
&cairo_image_surface_backend, /* backend */ \
CAIRO_SURFACE_TYPE_IMAGE, \
CAIRO_CONTENT_COLOR, \
CAIRO_REF_COUNT_INVALID, /* ref_count */ \
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ \
status, /* status */ \
FALSE, /* finished */ \
{ 0, /* size */ \
@ -188,7 +188,7 @@ _cairo_surface_init (cairo_surface_t *surface,
surface->content = content;
surface->type = backend->type;
surface->ref_count = 1;
CAIRO_REFERENCE_COUNT_INIT (&surface->ref_count, 1);
surface->status = CAIRO_STATUS_SUCCESS;
surface->finished = FALSE;
@ -372,12 +372,13 @@ _cairo_surface_get_clip_mode (cairo_surface_t *surface)
cairo_surface_t *
cairo_surface_reference (cairo_surface_t *surface)
{
if (surface == NULL || surface->ref_count == CAIRO_REF_COUNT_INVALID)
if (surface == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
return surface;
assert (surface->ref_count > 0);
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count));
surface->ref_count++;
_cairo_reference_count_inc (&surface->ref_count);
return surface;
}
@ -394,13 +395,13 @@ slim_hidden_def (cairo_surface_reference);
void
cairo_surface_destroy (cairo_surface_t *surface)
{
if (surface == NULL || surface->ref_count == CAIRO_REF_COUNT_INVALID)
if (surface == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
return;
assert (surface->ref_count > 0);
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count));
surface->ref_count--;
if (surface->ref_count)
if (! _cairo_reference_count_dec_and_test (&surface->ref_count))
return;
if (! surface->finished)
@ -422,10 +423,11 @@ slim_hidden_def(cairo_surface_destroy);
cairo_status_t
_cairo_surface_reset (cairo_surface_t *surface)
{
if (surface == NULL || surface->ref_count == CAIRO_REF_COUNT_INVALID)
if (surface == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
return CAIRO_STATUS_SUCCESS;
assert (surface->ref_count == 1);
assert (CAIRO_REFERENCE_COUNT_GET_VALUE (&surface->ref_count) == 1);
_cairo_user_data_array_fini (&surface->user_data);
@ -454,10 +456,11 @@ _cairo_surface_reset (cairo_surface_t *surface)
unsigned int
cairo_surface_get_reference_count (cairo_surface_t *surface)
{
if (surface == NULL || surface->ref_count == CAIRO_REF_COUNT_INVALID)
if (surface == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
return 0;
return surface->ref_count;
return CAIRO_REFERENCE_COUNT_GET_VALUE (&surface->ref_count);
}
/**
@ -486,7 +489,7 @@ cairo_surface_finish (cairo_surface_t *surface)
if (surface == NULL)
return;
if (surface->ref_count == CAIRO_REF_COUNT_INVALID)
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
return;
if (surface->finished) {
@ -557,7 +560,7 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
void *user_data,
cairo_destroy_func_t destroy)
{
if (surface->ref_count == CAIRO_REF_COUNT_INVALID)
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
return CAIRO_STATUS_NO_MEMORY;
return _cairo_user_data_array_set_data (&surface->user_data,

View file

@ -127,13 +127,9 @@ _cairo_xlib_display_reference (cairo_xlib_display_t *display)
if (display == NULL)
return NULL;
/* use our mutex until we get a real atomic inc */
CAIRO_MUTEX_LOCK (display->mutex);
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&display->ref_count));
assert (display->ref_count > 0);
display->ref_count++;
CAIRO_MUTEX_UNLOCK (display->mutex);
_cairo_reference_count_inc (&display->ref_count);
return display;
}
@ -144,27 +140,25 @@ _cairo_xlib_display_destroy (cairo_xlib_display_t *display)
if (display == NULL)
return;
CAIRO_MUTEX_LOCK (display->mutex);
assert (display->ref_count > 0);
if (--display->ref_count == 0) {
/* destroy all outstanding notifies */
while (display->workqueue != NULL) {
cairo_xlib_job_t *job = display->workqueue;
display->workqueue = job->next;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&display->ref_count));
if (job->type == WORK && job->func.work.destroy != NULL)
job->func.work.destroy (job->func.work.data);
if (! _cairo_reference_count_dec_and_test (&display->ref_count))
return;
_cairo_freelist_free (&display->wq_freelist, job);
}
_cairo_freelist_fini (&display->wq_freelist);
_cairo_freelist_fini (&display->hook_freelist);
/* destroy all outstanding notifies */
while (display->workqueue != NULL) {
cairo_xlib_job_t *job = display->workqueue;
display->workqueue = job->next;
CAIRO_MUTEX_UNLOCK (display->mutex);
if (job->type == WORK && job->func.work.destroy != NULL)
job->func.work.destroy (job->func.work.data);
free (display);
} else
CAIRO_MUTEX_UNLOCK (display->mutex);
_cairo_freelist_free (&display->wq_freelist, job);
}
_cairo_freelist_fini (&display->wq_freelist);
_cairo_freelist_fini (&display->hook_freelist);
free (display);
}
static int
@ -280,7 +274,7 @@ _cairo_xlib_display_get (Display *dpy)
_cairo_freelist_init (&display->wq_freelist, sizeof (cairo_xlib_job_t));
_cairo_freelist_init (&display->hook_freelist, sizeof (cairo_xlib_hook_t));
display->ref_count = 2; /* add one for the CloseDisplay */
CAIRO_REFERENCE_COUNT_INIT (&display->ref_count, 2); /* add one for the CloseDisplay */
CAIRO_MUTEX_INIT (display->mutex);
display->display = dpy;
display->screens = NULL;

View file

@ -39,6 +39,7 @@
#include "cairo-compiler-private.h"
#include "cairo-freelist-private.h"
#include "cairo-reference-count-private.h"
#include "cairo-xlib-xrender-private.h"
#include <X11/Xutil.h> /* for XDestroyImage */
@ -58,7 +59,7 @@ struct _cairo_xlib_hook {
struct _cairo_xlib_display {
cairo_xlib_display_t *next;
unsigned int ref_count;
cairo_reference_count_t ref_count;
cairo_mutex_t mutex;
Display *display;
@ -74,7 +75,7 @@ struct _cairo_xlib_display {
struct _cairo_xlib_screen_info {
cairo_xlib_screen_info_t *next;
unsigned int ref_count;
cairo_reference_count_t ref_count;
cairo_xlib_display_t *display;
Screen *screen;

View file

@ -246,8 +246,9 @@ _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
if (info == NULL)
return NULL;
assert (info->ref_count > 0);
info->ref_count++;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count));
_cairo_reference_count_inc (&info->ref_count);
return info;
}
@ -274,8 +275,9 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
if (info == NULL)
return;
assert (info->ref_count > 0);
if (--info->ref_count)
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count));
if (! _cairo_reference_count_dec_and_test (&info->ref_count))
return;
CAIRO_MUTEX_LOCK (info->display->mutex);
@ -330,7 +332,7 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
} else {
info = malloc (sizeof (cairo_xlib_screen_info_t));
if (info != NULL) {
info->ref_count = 2; /* Add one for display cache */
CAIRO_REFERENCE_COUNT_INIT (&info->ref_count, 2); /* Add one for display cache */
info->display = _cairo_xlib_display_reference (display);
info->screen = screen;
info->has_render = FALSE;

View file

@ -45,7 +45,7 @@
#define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
static const cairo_t _cairo_nil = {
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_NO_MEMORY, /* status */
{ 0, 0, 0, NULL }, /* user_data */
NULL, /* gstate */
@ -199,7 +199,7 @@ cairo_create (cairo_surface_t *target)
if (cr == NULL)
return (cairo_t *) &_cairo_nil;
cr->ref_count = 1;
CAIRO_REFERENCE_COUNT_INIT (&cr->ref_count, 1);
cr->status = CAIRO_STATUS_SUCCESS;
@ -232,12 +232,12 @@ slim_hidden_def (cairo_create);
cairo_t *
cairo_reference (cairo_t *cr)
{
if (cr == NULL || cr->ref_count == CAIRO_REF_COUNT_INVALID)
if (cr == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count))
return cr;
assert (cr->ref_count > 0);
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&cr->ref_count));
cr->ref_count++;
_cairo_reference_count_inc (&cr->ref_count);
return cr;
}
@ -253,13 +253,12 @@ cairo_reference (cairo_t *cr)
void
cairo_destroy (cairo_t *cr)
{
if (cr == NULL || cr->ref_count == CAIRO_REF_COUNT_INVALID)
if (cr == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count))
return;
assert (cr->ref_count > 0);
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&cr->ref_count));
cr->ref_count--;
if (cr->ref_count)
if (! _cairo_reference_count_dec_and_test (&cr->ref_count))
return;
while (cr->gstate != cr->gstate_tail) {
@ -323,7 +322,7 @@ cairo_set_user_data (cairo_t *cr,
void *user_data,
cairo_destroy_func_t destroy)
{
if (cr->ref_count == CAIRO_REF_COUNT_INVALID)
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count))
return CAIRO_STATUS_NO_MEMORY;
return _cairo_user_data_array_set_data (&cr->user_data,
@ -344,10 +343,10 @@ cairo_set_user_data (cairo_t *cr,
unsigned int
cairo_get_reference_count (cairo_t *cr)
{
if (cr == NULL || cr->ref_count == CAIRO_REF_COUNT_INVALID)
if (cr == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count))
return 0;
return cr->ref_count;
return CAIRO_REFERENCE_COUNT_GET_VALUE (&cr->ref_count);
}
/**

View file

@ -110,8 +110,6 @@ do { \
assert (NOT_REACHED); \
} while (0)
#define CAIRO_REF_COUNT_INVALID ((unsigned int) -1)
#define CAIRO_ALPHA_IS_OPAQUE(alpha) ((alpha) >= ((double)0xff00 / (double)0xffff))
#define CAIRO_ALPHA_SHORT_IS_OPAQUE(alpha) ((alpha) >= 0xff00)
#define CAIRO_ALPHA_IS_ZERO(alpha) ((alpha) <= 0.0)
@ -168,6 +166,7 @@ be32_to_cpu(uint32_t v)
#include "cairo-types-private.h"
#include "cairo-cache-private.h"
#include "cairo-fixed-private.h"
#include "cairo-reference-count-private.h"
typedef struct _cairo_region cairo_region_t;
@ -384,9 +383,9 @@ typedef struct _cairo_unscaled_font_backend cairo_unscaled_font_backend_t;
* glyph cache.
*/
typedef struct _cairo_unscaled_font {
cairo_hash_entry_t hash_entry;
unsigned int ref_count;
const cairo_unscaled_font_backend_t *backend;
cairo_hash_entry_t hash_entry;
cairo_reference_count_t ref_count;
const cairo_unscaled_font_backend_t *backend;
} cairo_unscaled_font_t;
typedef struct _cairo_scaled_glyph {
@ -410,7 +409,7 @@ struct _cairo_font_face {
/* hash_entry must be first */
cairo_hash_entry_t hash_entry;
cairo_status_t status;
unsigned int ref_count;
cairo_reference_count_t ref_count;
cairo_user_data_array_t user_data;
const cairo_font_face_backend_t *backend;
};
@ -883,14 +882,14 @@ typedef enum {
#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_BEST
struct _cairo_pattern {
cairo_pattern_type_t type;
unsigned int ref_count;
cairo_status_t status;
cairo_user_data_array_t user_data;
cairo_pattern_type_t type;
cairo_reference_count_t ref_count;
cairo_status_t status;
cairo_user_data_array_t user_data;
cairo_matrix_t matrix;
cairo_filter_t filter;
cairo_extend_t extend;
cairo_matrix_t matrix;
cairo_filter_t filter;
cairo_extend_t extend;
};
typedef struct _cairo_solid_pattern {