volatile conc_table *table; /* goes to HP0 */
GHashFunc hash_func;
GEqualFunc equal_func;
- mono_mutex_t *mutex;
int element_count;
int overflow_count;
GDestroyNotify key_destroy_func;
static void
conc_table_free (gpointer ptr)
{
- conc_table *table = ptr;
+ conc_table *table = (conc_table *)ptr;
g_free (table->kvs);
g_free (table);
}
static void
conc_table_lf_free (conc_table *table)
{
- mono_thread_hazardous_free_or_queue (table, conc_table_free, TRUE, FALSE);
+ mono_thread_hazardous_free_or_queue (table, conc_table_free, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
}
MonoConcurrentHashTable*
-mono_conc_hashtable_new (mono_mutex_t *mutex, GHashFunc hash_func, GEqualFunc key_equal_func)
+mono_conc_hashtable_new (GHashFunc hash_func, GEqualFunc key_equal_func)
{
MonoConcurrentHashTable *res = g_new0 (MonoConcurrentHashTable, 1);
- res->mutex = mutex;
res->hash_func = hash_func ? hash_func : g_direct_hash;
- res->equal_func = key_equal_func;
+ res->equal_func = key_equal_func ? key_equal_func : g_direct_equal;
// res->equal_func = g_direct_equal;
res->table = conc_table_new (INITIAL_SIZE);
res->element_count = 0;
}
MonoConcurrentHashTable*
-mono_conc_hashtable_new_full (mono_mutex_t *mutex, GHashFunc hash_func, GEqualFunc key_equal_func, GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
+mono_conc_hashtable_new_full (GHashFunc hash_func, GEqualFunc key_equal_func, GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
{
- MonoConcurrentHashTable *res = mono_conc_hashtable_new (mutex, hash_func, key_equal_func);
+ MonoConcurrentHashTable *res = mono_conc_hashtable_new (hash_func, key_equal_func);
res->key_destroy_func = key_destroy_func;
res->value_destroy_func = value_destroy_func;
return res;
hp = mono_hazard_pointer_get ();
retry:
- table = get_hazardous_pointer ((gpointer volatile*)&hash_table->table, hp, 0);
+ table = (conc_table *)get_hazardous_pointer ((gpointer volatile*)&hash_table->table, hp, 0);
table_mask = table->table_size - 1;
kvs = table->kvs;
i = hash & table_mask;
}
/**
- * mono_conc_hashtable_remove
+ * mono_conc_hashtable_remove:
+ *
+ * Remove a value from the hashtable. Requires external locking
*
* @Returns the old value if key is already present or null
*/
g_assert (key != NULL && key != TOMBSTONE);
hash = mix_hash (hash_table->hash_func (key));
- mono_mutex_lock (hash_table->mutex);
table = (conc_table*)hash_table->table;
kvs = table->kvs;
if (!hash_table->equal_func) {
for (;;) {
if (!kvs [i].key) {
- mono_mutex_unlock (hash_table->mutex);
return NULL; /*key not found*/
}
mono_memory_barrier ();
kvs [i].key = TOMBSTONE;
- mono_mutex_unlock (hash_table->mutex);
if (hash_table->key_destroy_func != NULL)
(*hash_table->key_destroy_func) (key);
if (hash_table->value_destroy_func != NULL)
GEqualFunc equal = hash_table->equal_func;
for (;;) {
if (!kvs [i].key) {
- mono_mutex_unlock (hash_table->mutex);
return NULL; /*key not found*/
}
mono_memory_barrier ();
kvs [i].key = TOMBSTONE;
- mono_mutex_unlock (hash_table->mutex);
if (hash_table->key_destroy_func != NULL)
(*hash_table->key_destroy_func) (old_key);
if (hash_table->value_destroy_func != NULL)
}
}
/**
- * mono_conc_hashtable_insert
- *
+ * mono_conc_hashtable_insert:
+ *
+ * Insert a value into the hashtable. Requires external locking.
* @Returns the old value if key is already present or null
*/
gpointer
g_assert (value != NULL);
hash = mix_hash (hash_table->hash_func (key));
- mono_mutex_lock (hash_table->mutex);
if (hash_table->element_count >= hash_table->overflow_count)
expand_table (hash_table);
mono_memory_barrier ();
kvs [i].key = key;
++hash_table->element_count;
- mono_mutex_unlock (hash_table->mutex);
return NULL;
}
if (key == kvs [i].key) {
gpointer value = kvs [i].value;
- mono_mutex_unlock (hash_table->mutex);
return value;
}
i = (i + 1) & table_mask;
mono_memory_barrier ();
kvs [i].key = key;
++hash_table->element_count;
- mono_mutex_unlock (hash_table->mutex);
return NULL;
}
if (equal (key, kvs [i].key)) {
gpointer value = kvs [i].value;
- mono_mutex_unlock (hash_table->mutex);
return value;
}
i = (i + 1) & table_mask;
}
}
+/**
+ * mono_conc_hashtable_foreach:
+ *
+ * Calls @func for each value in the hashtable. Requires external locking.
+ */
+void
+mono_conc_hashtable_foreach (MonoConcurrentHashTable *hash_table, GHFunc func, gpointer userdata)
+{
+ int i;
+ conc_table *table = (conc_table*)hash_table->table;
+ key_value_pair *kvs = table->kvs;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ for (i = 0; i < table->table_size; ++i) {
+ if (kvs [i].key && kvs [i].key != TOMBSTONE) {
+ func (kvs [i].key, kvs [i].value, userdata);
+ }
+ }
+}