Author: miguel
Date: 2006-08-21 01:55:48 -0400 (Mon, 21 Aug 2006)
New Revision: 64121
Modified:
trunk/mono/eglib/ChangeLog
trunk/mono/eglib/src/ghashtable.c
trunk/mono/eglib/src/glib.h
trunk/mono/eglib/test/hashtable.c
Log:
2006-08-21 Miguel de Icaza <[EMAIL PROTECTED]>
* src/glib.h (g_hash_table_new_full): Add missing prototype.
Replace g_free(x) with plain free, so it can be used as a function
argument.
Add ABS
* src/ghashtable.c: Add rehashing.
* test/hashtable.c: Add a bunch of extra tests.
Modified: trunk/mono/eglib/ChangeLog
===================================================================
--- trunk/mono/eglib/ChangeLog 2006-08-21 05:11:02 UTC (rev 64120)
+++ trunk/mono/eglib/ChangeLog 2006-08-21 05:55:48 UTC (rev 64121)
@@ -1,5 +1,14 @@
2006-08-21 Miguel de Icaza <[EMAIL PROTECTED]>
+ * src/glib.h (g_hash_table_new_full): Add missing prototype.
+ Replace g_free(x) with plain free, so it can be used as a function
+ argument.
+ Add ABS
+
+ * src/ghashtable.c: Add rehashing.
+
+ * test/hashtable.c: Add a bunch of extra tests.
+
* src/goutput.c: Fix g_log so it actually formats the data.
* src/ghashtable.c (g_hash_table_new): The glib test suite
Modified: trunk/mono/eglib/src/ghashtable.c
===================================================================
--- trunk/mono/eglib/src/ghashtable.c 2006-08-21 05:11:02 UTC (rev 64120)
+++ trunk/mono/eglib/src/ghashtable.c 2006-08-21 05:55:48 UTC (rev 64121)
@@ -47,6 +47,7 @@
int table_size;
int in_use;
int threshold;
+ int last_rehash;
GDestroyNotify value_destroy_func, key_destroy_func;
};
@@ -97,16 +98,6 @@
return calc_prime (x);
}
-static void
-adjust_threshold (GHashTable *hash)
-{
- hash->threshold = (int) hash->table_size * 0.75;
- if (hash->threshold >= hash->table_size)
- hash->threshold = hash->table_size-1;
- if (hash->threshold == 0)
- hash->threshold = 1;
-}
-
GHashTable *
g_hash_table_new (GHashFunc hash_func, GEqualFunc key_equal_func)
{
@@ -123,7 +114,7 @@
hash->table_size = to_prime (1);
hash->table = g_new0 (Slot *, hash->table_size);
- adjust_threshold (hash);
+ hash->last_rehash = hash->table_size;
return hash;
}
@@ -143,9 +134,42 @@
}
void
+do_rehash (GHashTable *hash)
+{
+ int current_size, i;
+ Slot **table;
+
+ /* printf ("Resizing diff=%d slots=%d\n", hash->in_use -
hash->last_rehash, hash->table_size); */
+ hash->last_rehash = hash->table_size;
+ current_size = hash->table_size;
+ hash->table_size = to_prime (hash->in_use);
+ /* printf ("New size: %d\n", hash->table_size); */
+ table = hash->table;
+ hash->table = g_new0 (Slot *, hash->table_size);
+
+ for (i = 0; i < current_size; i++){
+ Slot *s, *next;
+
+ for (s = table [i]; s != NULL; s = next){
+ guint hashcode = ((*hash->hash_func) (s->key)) %
hash->table_size;
+ next = s->next;
+
+ s->next = hash->table [hashcode];
+ hash->table [hashcode] = s;
+ }
+ }
+ g_free (table);
+}
+
+void
rehash (GHashTable *hash)
{
- /* FIXME */
+ int diff = ABS (hash->last_rehash, hash->in_use);
+
+ /* These are the factors to play with to change the rehashing strategy
*/
+ if (!(diff * 0.75 > hash->table_size * 2))
+ return;
+ do_rehash (hash);
}
void
Modified: trunk/mono/eglib/src/glib.h
===================================================================
--- trunk/mono/eglib/src/glib.h 2006-08-21 05:11:02 UTC (rev 64120)
+++ trunk/mono/eglib/src/glib.h 2006-08-21 05:55:48 UTC (rev 64121)
@@ -50,6 +50,8 @@
#define G_STMT_START do
#define G_STMT_END while (0)
+#define ABS(a,b) (((a)>(b)) ? ((a)-(b)) : ((b)-(a)))
+
#define G_STRUCT_OFFSET(p_type,field) \
((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL)))
@@ -59,7 +61,6 @@
*/
#define g_new(type,size) ((type *) malloc (sizeof (type) * (size)))
#define g_new0(type,size) ((type *) calloc (sizeof (type), (size)))
-#define g_free(obj) free (obj)
#define g_realloc(obj,size) realloc((obj), (size))
#define g_strdup(x) strdup(x)
#define g_malloc(x) malloc(x)
@@ -69,6 +70,7 @@
#define g_memmove(dest,src,len) memmove (dest, src, len)
#define g_renew(struct_type, mem, n_structs) realloc (mem, sizeof
(struct_type) * n_structs)
#define g_alloca(size) alloca (size)
+#define g_free free
gpointer g_memdup (gconstpointer mem, guint byte_size);
@@ -101,6 +103,8 @@
typedef gboolean (*GEqualFunc) (gconstpointer a, gconstpointer b);
GHashTable *g_hash_table_new (GHashFunc hash_func, GEqualFunc
key_equal_func);
+GHashTable *g_hash_table_new_full (GHashFunc hash_func, GEqualFunc
key_equal_func,
+ GDestroyNotify key_destroy_func,
GDestroyNotify value_destroy_func);
void g_hash_table_insert_replace (GHashTable *hash, gpointer key,
gpointer value, gboolean replace);
guint g_hash_table_size (GHashTable *hash);
gpointer g_hash_table_lookup (GHashTable *hash, gconstpointer
key);
Modified: trunk/mono/eglib/test/hashtable.c
===================================================================
--- trunk/mono/eglib/test/hashtable.c 2006-08-21 05:11:02 UTC (rev 64120)
+++ trunk/mono/eglib/test/hashtable.c 2006-08-21 05:55:48 UTC (rev 64121)
@@ -50,9 +50,92 @@
return OK;
}
+RESULT hash_default (void)
+{
+ GHashTable *hash = g_hash_table_new (NULL, NULL);
+
+ if (hash == NULL)
+ return FAILED ("g_hash_table_new should return a valid hash");
+
+ return NULL;
+}
+
+RESULT
+hash_null_lookup (void)
+{
+ GHashTable *hash = g_hash_table_new (NULL, NULL);
+ gpointer ok, ov;
+
+ g_hash_table_insert (hash, NULL, GINT_TO_POINTER (1));
+ g_hash_table_insert (hash, GINT_TO_POINTER(1), GINT_TO_POINTER(2));
+
+ if (!g_hash_table_lookup_extended (hash, NULL, &ok, &ov))
+ return FAILED ("Did not find the NULL");
+ if (ok != NULL)
+ return FAILED ("Incorrect key found");
+ if (ov != GINT_TO_POINTER (1))
+ return FAILED ("Got wrong value %p\n", ov);
+
+ if (!g_hash_table_lookup_extended (hash, GINT_TO_POINTER(1), &ok, &ov))
+ return FAILED ("Did not find the 1");
+ if (ok != GINT_TO_POINTER(1))
+ return FAILED ("Incorrect key found");
+ if (ov != GINT_TO_POINTER (2))
+ return FAILED ("Got wrong value %p\n", ov);
+
+ g_hash_table_destroy (hash);
+
+ return NULL;
+}
+
+static void
+counter (gpointer key, gpointer value, gpointer user_data)
+{
+ int *counter = (int *) user_data;
+
+ (*counter)++;
+}
+
+RESULT hash_grow (void)
+{
+ GHashTable *hash = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
+ int i, count = 0;
+
+ for (i = 0; i < 1000; i++)
+ g_hash_table_insert (hash, g_strdup_printf ("%d", i),
g_strdup_printf ("x-%d", i));
+
+ for (i = 0; i < 1000; i++){
+ char buffer [30];
+ gpointer value;
+
+ sprintf (buffer, "%d", i);
+
+ value = g_hash_table_lookup (hash, buffer);
+ sprintf (buffer, "x-%d", i);
+ if (strcmp (value, buffer) != 0){
+ return FAILED ("Failed to lookup the key %d, the value
was %s\n", i, value);
+ }
+ }
+
+ if (g_hash_table_size (hash) != 1000)
+ return FAILED ("Did not find 1000 elements on the hash, found
%d\n", g_hash_table_size (hash));
+
+ /* Now do the manual count, lets not trust the internals */
+ g_hash_table_foreach (hash, counter, &count);
+ if (count != 1000){
+ return FAILED ("Foreach count is not 1000");
+ }
+
+ g_hash_table_destroy (hash);
+ return NULL;
+}
+
static Test hashtable_tests [] = {
{"hash_t1", hash_t1},
{"hash_t2", hash_t2},
+ {"hash_grow", hash_grow},
+ {"hash_default", hash_default},
+ {"hash_null_lookup", hash_null_lookup},
{NULL, NULL}
};
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches