[cache] Expose init/fini methods so that caches can be embedded.

The structure is already exposed, so just expose the
constructors/destructors in order to enable caches to be embedded and
remove a superfluous malloc.
This commit is contained in:
Chris Wilson 2009-05-26 12:46:46 +01:00
parent c3aac9cf49
commit 45835f623f
4 changed files with 74 additions and 106 deletions

View file

@ -88,6 +88,20 @@ typedef struct _cairo_cache_entry {
unsigned long size;
} cairo_cache_entry_t;
typedef cairo_bool_t (*cairo_cache_predicate_func_t) (const void *entry);
struct _cairo_cache {
cairo_hash_table_t *hash_table;
cairo_cache_predicate_func_t predicate;
cairo_destroy_func_t entry_destroy;
unsigned long max_size;
unsigned long size;
int freeze_count;
};
typedef cairo_bool_t
(*cairo_cache_keys_equal_func_t) (const void *key_a, const void *key_b);
@ -95,14 +109,15 @@ typedef void
(*cairo_cache_callback_func_t) (void *entry,
void *closure);
cairo_private cairo_cache_t *
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size);
cairo_private cairo_status_t
_cairo_cache_init (cairo_cache_t *cache,
cairo_cache_keys_equal_func_t keys_equal,
cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size);
cairo_private void
_cairo_cache_destroy (cairo_cache_t *cache);
_cairo_cache_fini (cairo_cache_t *cache);
cairo_private void
_cairo_cache_freeze (cairo_cache_t *cache);

View file

@ -48,48 +48,10 @@ _cairo_cache_entry_is_non_zero (const void *entry)
return ((const cairo_cache_entry_t *) entry)->size;
}
static cairo_status_t
_cairo_cache_init (cairo_cache_t *cache,
cairo_cache_keys_equal_func_t keys_equal,
cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size)
{
cache->hash_table = _cairo_hash_table_create (keys_equal);
if (unlikely (cache->hash_table == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (predicate == NULL)
predicate = _cairo_cache_entry_is_non_zero;
cache->predicate = predicate;
cache->entry_destroy = entry_destroy;
cache->max_size = max_size;
cache->size = 0;
cache->freeze_count = 0;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_cache_pluck (void *entry, void *closure)
{
_cairo_cache_remove (closure, entry);
}
static void
_cairo_cache_fini (cairo_cache_t *cache)
{
_cairo_hash_table_foreach (cache->hash_table,
_cairo_cache_pluck,
cache);
assert (cache->size == 0);
_cairo_hash_table_destroy (cache->hash_table);
}
/**
* _cairo_cache_create:
* _cairo_cache_init:
* @cache: the #cairo_cache_t to initialise
* @keys_equal: a function to return %TRUE if two keys are equal
* @entry_destroy: destroy notifier for cache entries
* @max_size: the maximum size for this cache
@ -122,49 +84,53 @@ _cairo_cache_fini (cairo_cache_t *cache)
* used to establish a window during which no automatic removal of
* entries will occur.
**/
cairo_cache_t *
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size)
cairo_status_t
_cairo_cache_init (cairo_cache_t *cache,
cairo_cache_keys_equal_func_t keys_equal,
cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size)
{
cairo_status_t status;
cairo_cache_t *cache;
cache->hash_table = _cairo_hash_table_create (keys_equal);
if (unlikely (cache->hash_table == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
cache = malloc (sizeof (cairo_cache_t));
if (unlikely (cache == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
if (predicate == NULL)
predicate = _cairo_cache_entry_is_non_zero;
cache->predicate = predicate;
cache->entry_destroy = entry_destroy;
status = _cairo_cache_init (cache,
keys_equal,
predicate,
entry_destroy,
max_size);
if (unlikely (status)) {
free (cache);
return NULL;
}
cache->max_size = max_size;
cache->size = 0;
return cache;
cache->freeze_count = 0;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_cache_pluck (void *entry, void *closure)
{
_cairo_cache_remove (closure, entry);
}
/**
* _cairo_cache_destroy:
* _cairo_cache_fini:
* @cache: a cache to destroy
*
* Immediately destroys the given cache, freeing all resources
* associated with it. As part of this process, the entry_destroy()
* function, (as passed to _cairo_cache_create()), will be called for
* function, (as passed to _cairo_cache_init()), will be called for
* each entry in the cache.
**/
void
_cairo_cache_destroy (cairo_cache_t *cache)
_cairo_cache_fini (cairo_cache_t *cache)
{
_cairo_cache_fini (cache);
free (cache);
_cairo_hash_table_foreach (cache->hash_table,
_cairo_cache_pluck,
cache);
assert (cache->size == 0);
_cairo_hash_table_destroy (cache->hash_table);
}
/**
@ -222,7 +188,7 @@ _cairo_cache_thaw (cairo_cache_t *cache)
*
* Performs a lookup in @cache looking for an entry which has a key
* that matches @key, (as determined by the keys_equal() function
* passed to _cairo_cache_create()).
* passed to _cairo_cache_init()).
*
* Return value: %TRUE if there is an entry in the cache that matches
* @key, (which will now be in *entry_return). %FALSE otherwise, (in

View file

@ -64,7 +64,7 @@
/* XXX: This number is arbitrary---we've never done any measurement of this. */
#define MAX_GLYPH_PAGES_CACHED 512
static cairo_cache_t *cairo_scaled_glyph_page_cache;
static cairo_cache_t cairo_scaled_glyph_page_cache;
#define CAIRO_SCALED_GLYPH_PAGE_SIZE 32
struct _cairo_scaled_glyph_page {
@ -745,7 +745,7 @@ _cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
if (scaled_font->global_cache_frozen) {
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
_cairo_cache_thaw (cairo_scaled_glyph_page_cache);
_cairo_cache_thaw (&cairo_scaled_glyph_page_cache);
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
scaled_font->global_cache_frozen = FALSE;
@ -761,7 +761,7 @@ _cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font)
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
while (scaled_font->glyph_pages != NULL) {
_cairo_cache_remove (cairo_scaled_glyph_page_cache,
_cairo_cache_remove (&cairo_scaled_glyph_page_cache,
&scaled_font->glyph_pages->cache_entry);
}
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
@ -1072,9 +1072,9 @@ _cairo_scaled_font_reset_static_data (void)
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex);
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
if (cairo_scaled_glyph_page_cache != NULL) {
_cairo_cache_destroy (cairo_scaled_glyph_page_cache);
cairo_scaled_glyph_page_cache = NULL;
if (cairo_scaled_glyph_page_cache.hash_table != NULL) {
_cairo_cache_fini (&cairo_scaled_glyph_page_cache);
cairo_scaled_glyph_page_cache.hash_table = NULL;
}
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
}
@ -2469,24 +2469,24 @@ _cairo_scaled_font_allocate_glyph (cairo_scaled_font_t *scaled_font,
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
if (scaled_font->global_cache_frozen == FALSE) {
if (unlikely (cairo_scaled_glyph_page_cache == NULL)) {
cairo_scaled_glyph_page_cache =
_cairo_cache_create (NULL,
_cairo_scaled_glyph_page_can_remove,
_cairo_scaled_glyph_page_destroy,
MAX_GLYPH_PAGES_CACHED);
if (unlikely (cairo_scaled_glyph_page_cache == NULL)) {
if (unlikely (cairo_scaled_glyph_page_cache.hash_table == NULL)) {
status = _cairo_cache_init (&cairo_scaled_glyph_page_cache,
NULL,
_cairo_scaled_glyph_page_can_remove,
_cairo_scaled_glyph_page_destroy,
MAX_GLYPH_PAGES_CACHED);
if (unlikely (status)) {
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
free (page);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return status;
}
}
_cairo_cache_freeze (cairo_scaled_glyph_page_cache);
_cairo_cache_freeze (&cairo_scaled_glyph_page_cache);
scaled_font->global_cache_frozen = TRUE;
}
status = _cairo_cache_insert (cairo_scaled_glyph_page_cache,
status = _cairo_cache_insert (&cairo_scaled_glyph_page_cache,
&page->cache_entry);
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
if (unlikely (status)) {
@ -2516,7 +2516,8 @@ _cairo_scaled_font_free_last_glyph (cairo_scaled_font_t *scaled_font,
_cairo_scaled_glyph_fini (scaled_font, scaled_glyph);
if (--page->num_glyphs == 0) {
_cairo_cache_remove (cairo_scaled_glyph_page_cache, &page->cache_entry);
_cairo_cache_remove (&cairo_scaled_glyph_page_cache,
&page->cache_entry);
assert (scaled_font->glyph_pages != page);
}
}

View file

@ -122,20 +122,6 @@ struct _cairo_font_options {
cairo_hint_metrics_t hint_metrics;
};
typedef cairo_bool_t (*cairo_cache_predicate_func_t) (const void *entry);
struct _cairo_cache {
cairo_hash_table_t *hash_table;
cairo_cache_predicate_func_t predicate;
cairo_destroy_func_t entry_destroy;
unsigned long max_size;
unsigned long size;
int freeze_count;
};
/* XXX: Right now, the _cairo_color structure puts unpremultiplied
color in the doubles and premultiplied color in the shorts. Yes,
this is crazy insane, (but at least we don't export this