[cairo-commit]
cairo/src cairo-hash-private.h, 1.3, 1.4 cairo-hash.c, 1.17, 1.18
Carl Worth
commit at pdx.freedesktop.org
Tue Jul 12 14:43:39 PDT 2005
- Previous message: [cairo-commit] cairo-perl/examples/png caps_joins.pl, 1.1,
1.2 hering.pl, 1.1, 1.2 outline.pl, 1.1, 1.2 spiral.pl, 1.1,
1.2 splines_tolerance.pl, 1.1, 1.2 stars.pl, 1.1, 1.2
- Next message: [cairo-commit] cairo ChangeLog,1.713,1.714
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Committed by: cworth
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv5929/src
Modified Files:
cairo-hash-private.h cairo-hash.c
Log Message:
* src/cairo-hash-private.h:
* src/cairo-hash.c:
(_cairo_hash_table_create): Remove destroy notifier. This
simplifies the implementation a bit, and no anticipated use of
cairo_hash_table_t in cairo needs the destroy notifier. Most uses
will be hash-backed object create/destroy functions.
(_cairo_hash_table_destroy): Document that it is now a fatal
error to call _cairo_hash_table_destroy on a non-empty hash table.
(_cairo_hash_table_insert): Document that it is now a fatal
error to insert an entry with a key that matches an existing
entry.
(_cairo_hash_table_random_entry): Add predicate function so that
the user can select a random entry satisying the given predicate.
(_cairo_hash_table_remove): Change return type to void since
failure is really not possible here.
Index: cairo-hash-private.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-hash-private.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- cairo-hash-private.h 30 Jun 2005 00:02:37 -0000 1.3
+++ cairo-hash-private.h 12 Jul 2005 21:43:37 -0000 1.4
@@ -39,7 +39,10 @@
#ifndef CAIRO_HASH_PRIVATE_H
#define CAIRO_HASH_PRIVATE_H
-#include "cairoint.h"
+/* XXX: I'd like this file to be self-contained in terms of
+ * includeability, but that's not really possible with the current
+ * monolithic cairoint.h. So, for now, just include cairoint.h instead
+ * if you want to include this file. */
typedef struct _cairo_hash_table cairo_hash_table_t;
@@ -63,8 +66,11 @@
* _cairo_hash_table_insert (hash_table, &my_entry->base);
*
* IMPORTANT: The caller is reponsible for initializing
- * my_entry->base.hash with a reasonable hash code derived from the
- * key.
+ * my_entry->base.hash with a hash code derived from the key. The
+ * essential property of the hash code is that keys_equal must never
+ * return TRUE for two keys that have different hashes. The best hash
+ * code will reduce the frequency of two keys with the same code for
+ * which keys_equal returns FALSE.
*
* Which parts of the entry make up the "key" and which part make up
* the value are entirely up to the caller, (as determined by the
@@ -79,15 +85,17 @@
} cairo_hash_entry_t;
typedef cairo_bool_t
-(*cairo_hash_keys_equal_func_t) (void *entry_a, void *entry_b);
+(*cairo_hash_keys_equal_func_t) (void *key_a, void *key_b);
+
+typedef cairo_bool_t
+(*cairo_hash_predicate_func_t) (void *entry);
typedef void
(*cairo_hash_callback_func_t) (void *entry,
void *closure);
cairo_private cairo_hash_table_t *
-_cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal,
- cairo_destroy_func_t entry_destroy);
+_cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal);
cairo_private void
_cairo_hash_table_destroy (cairo_hash_table_t *hash_table);
@@ -98,13 +106,14 @@
cairo_hash_entry_t **entry_return);
cairo_private void *
-_cairo_hash_table_random_entry (cairo_hash_table_t *hash_table);
+_cairo_hash_table_random_entry (cairo_hash_table_t *hash_table,
+ cairo_hash_predicate_func_t predicate);
cairo_private cairo_status_t
_cairo_hash_table_insert (cairo_hash_table_t *hash_table,
cairo_hash_entry_t *entry);
-cairo_private cairo_status_t
+cairo_private void
_cairo_hash_table_remove (cairo_hash_table_t *hash_table,
cairo_hash_entry_t *key);
Index: cairo-hash.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-hash.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- cairo-hash.c 30 Jun 2005 00:05:31 -0000 1.17
+++ cairo-hash.c 12 Jul 2005 21:43:37 -0000 1.18
@@ -36,7 +36,7 @@
* Carl Worth <cworth at cworth.org>
*/
-#include "cairo-hash-private.h"
+#include "cairoint.h"
/*
* An entry can be in one of three states:
@@ -119,7 +119,6 @@
struct _cairo_hash_table {
cairo_hash_keys_equal_func_t keys_equal;
- cairo_destroy_func_t entry_destroy;
const cairo_hash_table_arrangement_t *arrangement;
cairo_hash_entry_t **entries;
@@ -130,7 +129,6 @@
/**
* _cairo_hash_table_create:
* @keys_equal: a function to return TRUE if two keys are equal
- * @entry_destroy: destroy notifier for hash entries
*
* Creates a new hash table which will use the keys_equal() function
* to compare hash keys. Data is provided to the hash table in the
@@ -145,8 +143,7 @@
* Return value: the new hash table or NULL if out of memory.
**/
cairo_hash_table_t *
-_cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal,
- cairo_destroy_func_t entry_destroy)
+_cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal)
{
cairo_hash_table_t *hash_table;
@@ -155,7 +152,6 @@
return NULL;
hash_table->keys_equal = keys_equal;
- hash_table->entry_destroy = entry_destroy;
hash_table->arrangement = &hash_table_arrangements[0];
@@ -171,41 +167,27 @@
return hash_table;
}
-static void
-_destroy_entry (cairo_hash_table_t *hash_table, cairo_hash_entry_t **entry)
-{
- if (! ENTRY_IS_LIVE (*entry))
- return;
-
- if (hash_table->entry_destroy)
- hash_table->entry_destroy (*entry);
- *entry = DEAD_ENTRY;
- hash_table->live_entries--;
-}
-
/**
* _cairo_hash_table_destroy:
- * @hash_table: a hash table to destroy
+ * @hash_table: an empty hash table to destroy
*
* Immediately destroys the given hash table, freeing all resources
- * associated with it. As part of this process, the entry_destroy()
- * function, (as passed to cairo_hash_table_create), will be called
- * for each live entry in the hash table.
+ * associated with it.
+ *
+ * WARNING: The hash_table must have no live entries in it before
+ * _cairo_hash_table_destroy is called. It is a fatal error otherwise,
+ * and this function will halt. The rationale for this behavior is to
+ * avoid memory leaks and to avoid needless complication of the API
+ * with destroy notifiy callbacks.
**/
void
_cairo_hash_table_destroy (cairo_hash_table_t *hash_table)
{
- unsigned long i;
- cairo_hash_entry_t **entry;
-
if (hash_table == NULL)
return;
-
- for (i = 0; i < hash_table->arrangement->size; i++) {
- entry = &hash_table->entries[i];
- if (ENTRY_IS_LIVE(*entry))
- _destroy_entry (hash_table, entry);
- }
+
+ /* The hash table must be empty. Otherwise, halt. */
+ assert (hash_table->live_entries == 0);
free (hash_table->entries);
hash_table->entries = NULL;
@@ -366,7 +348,7 @@
*
* Performs a lookup in @hash_table looking for an entry which has a
* key that matches @key, (as determined by the keys_equal() function
- * passed to cairo_hash_table_create).
+ * passed to _cairo_hash_table_create).
*
* Return value: TRUE if there is an entry in the hash table that
* matches the given key, (which will now be in *entry_return). FALSE
@@ -393,24 +375,26 @@
/**
* _cairo_hash_table_random_entry:
* @hash_table: a hash table
+ * @predicate: a predicate function, or NULL for any entry.
*
- * Find a random entry in the hash table.
+ * Find a random entry in the hash table satisfying the given
+ * @predicate. A NULL @predicate is taken as equivalent to a function
+ * which always returns TRUE, (eg. any entry in the table will do).
*
* We use the same algorithm as the lookup algorithm to walk over the
* entries in the hash table in a pseudo-random order. Walking
* linearly would favor entries following gaps in the hash table. We
* could also call rand() repeatedly, which works well for almost-full
* tables, but degrades when the table is almost empty, or predicate
- * returns false for most entries.
+ * returns TRUE for most entries.
*
- * NOTE: It'd be really easy to turn this into a find function with a
- * predicate if anybody might want that.
- *
- * Return value: a random live entry or NULL if there are no live
- * entries.
+ * Return value: a random live entry or NULL if there are no entries
+ * that match the given predicate. In particular, if predicate is
+ * NULL, a NULL return value indicates that the table is empty.
**/
void *
-_cairo_hash_table_random_entry (cairo_hash_table_t *hash_table)
+_cairo_hash_table_random_entry (cairo_hash_table_t *hash_table,
+ cairo_hash_predicate_func_t predicate)
{
cairo_hash_entry_t **entry;
unsigned long hash;
@@ -426,8 +410,11 @@
{
entry = &hash_table->entries[idx];
- if (ENTRY_IS_LIVE (*entry))
+ if (ENTRY_IS_LIVE (*entry) &&
+ (predicate == NULL || predicate (*entry)))
+ {
return *entry;
+ }
if (step == 0) {
step = hash % hash_table->arrangement->rehash;
@@ -448,10 +435,14 @@
* @hash_table: a hash table
* @key_and_value: an entry to be inserted
*
- * Insert the entry #key_and_value into the hash table. If an existing
- * exists in the hash table with a matching key, then the old entry
- * will be removed first, (and the entry_destroy() callback will be
- * called on it).
+ * Insert the entry #key_and_value into the hash table.
+ *
+ * WARNING: It is a fatal error if an entry exists in the hash table
+ * with a matching key, (this function will halt).
+ *
+ * Instead of using insert to replace an entry, consider just editing
+ * the entry obtained with _cairo_hash_table_lookup. Or if absolutely
+ * necessary, use _cairo_hash_table_remove first.
*
* Return value: CAIRO_STATUS_SUCCESS if successful or
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
@@ -468,16 +459,12 @@
if (ENTRY_IS_LIVE(*entry))
{
- if (hash_table->entry_destroy)
- hash_table->entry_destroy (*entry);
- *entry = key_and_value;
+ /* User is being bad, let's crash. */
+ ASSERT_NOT_REACHED;
}
- else
- {
- *entry = key_and_value;
- hash_table->live_entries++;
- }
+ *entry = key_and_value;
+ hash_table->live_entries++;
status = _cairo_hash_table_resize (hash_table);
if (status)
@@ -492,30 +479,30 @@
* @key: key of entry to be removed
*
* Remove an entry from the hash table which has a key that matches
- * @key, (as determined by the keys_equal() function passed to
- * _cairo_hash_table_create), if any.
+ * @key, if any (as determined by the keys_equal() function passed to
+ * _cairo_hash_table_create).
*
* Return value: CAIRO_STATUS_SUCCESS if successful or
* CAIRO_STATUS_NO_MEMORY if out of memory.
**/
-cairo_status_t
+void
_cairo_hash_table_remove (cairo_hash_table_t *hash_table,
cairo_hash_entry_t *key)
{
- cairo_status_t status;
cairo_hash_entry_t **entry;
entry = _cairo_hash_table_lookup_internal (hash_table, key, FALSE);
if (! ENTRY_IS_LIVE(*entry))
- return CAIRO_STATUS_SUCCESS;
-
- _destroy_entry (hash_table, entry);
+ return;
- status = _cairo_hash_table_resize (hash_table);
- if (status)
- return status;
+ *entry = DEAD_ENTRY;
+ hash_table->live_entries--;
- return CAIRO_STATUS_SUCCESS;
+ /* This call _can_ fail, but only in failing to allocate new
+ * memory to shrink the hash table. It does leave the table in a
+ * consistent state, and we've already succeeded in removing the
+ * entry, so we don't examine the failure status of this call. */
+ _cairo_hash_table_resize (hash_table);
}
/**
- Previous message: [cairo-commit] cairo-perl/examples/png caps_joins.pl, 1.1,
1.2 hering.pl, 1.1, 1.2 outline.pl, 1.1, 1.2 spiral.pl, 1.1,
1.2 splines_tolerance.pl, 1.1, 1.2 stars.pl, 1.1, 1.2
- Next message: [cairo-commit] cairo ChangeLog,1.713,1.714
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the cairo-commit
mailing list