mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 19:18:12 +02:00
[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:
parent
c3aac9cf49
commit
45835f623f
4 changed files with 74 additions and 106 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue