mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-01-22 20:42:03 -08:00
hash-table: add synchronization implementation
This commit is contained in:
parent
c88af87046
commit
57bdf6e989
3 changed files with 65 additions and 3 deletions
56
src/c/hash.d
56
src/c/hash.d
|
|
@ -653,7 +653,42 @@ _ecl_remhash_weak(cl_object key, cl_object hashtable)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* SYNCHRONIZED HASH TABLES */
|
||||
#ifdef ECL_THREADS
|
||||
static cl_object
|
||||
_ecl_sethash_sync(cl_object key, cl_object hashtable, cl_object value)
|
||||
{
|
||||
cl_object output = ECL_NIL;
|
||||
cl_object sync_lock = hashtable->hash.sync_lock;
|
||||
mp_get_rwlock_write_wait(sync_lock);
|
||||
output = hashtable->hash.set_unsafe(key, hashtable, value);
|
||||
mp_giveup_rwlock_write(sync_lock);
|
||||
return output;
|
||||
}
|
||||
|
||||
static cl_object
|
||||
_ecl_gethash_sync(cl_object key, cl_object hashtable, cl_object def)
|
||||
{
|
||||
cl_object output = ECL_NIL;
|
||||
cl_object sync_lock = hashtable->hash.sync_lock;
|
||||
mp_get_rwlock_read_wait(sync_lock);
|
||||
output = hashtable->hash.get_unsafe(key, hashtable, def);
|
||||
mp_giveup_rwlock_read(sync_lock);
|
||||
return output;
|
||||
}
|
||||
|
||||
static bool
|
||||
_ecl_remhash_sync(cl_object key, cl_object hashtable)
|
||||
{
|
||||
bool output = 0;
|
||||
cl_object sync_lock = hashtable->hash.sync_lock;
|
||||
mp_get_rwlock_write_wait(sync_lock);
|
||||
output = hashtable->hash.rem_unsafe(key, hashtable);
|
||||
mp_giveup_rwlock_write(sync_lock);
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -775,6 +810,22 @@ ecl_extend_hashtable(cl_object hashtable)
|
|||
hash->hash.rem = _ecl_remhash_weak;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!Null(synchronized)) {
|
||||
#ifdef ECL_THREADS
|
||||
hash->hash.sync_lock = ecl_make_rwlock(ECL_NIL);
|
||||
hash->hash.get_unsafe = hash->hash.get;
|
||||
hash->hash.set_unsafe = hash->hash.set;
|
||||
hash->hash.rem_unsafe = hash->hash.rem;
|
||||
hash->hash.get = _ecl_gethash_sync;
|
||||
hash->hash.set = _ecl_sethash_sync;
|
||||
hash->hash.rem = _ecl_remhash_sync;
|
||||
#else
|
||||
/* for hash-table-synchronized-p predicate */
|
||||
hash->hash.sync_lock = ECL_T;
|
||||
#endif
|
||||
}
|
||||
|
||||
@(return hash);
|
||||
} @)
|
||||
|
||||
|
|
@ -924,11 +975,10 @@ si_hash_table_weakness(cl_object ht)
|
|||
cl_object
|
||||
si_hash_table_synchronized_p(cl_object ht)
|
||||
{
|
||||
#if 0
|
||||
if (ht->hash.sync) {
|
||||
|
||||
if (!Null(ht->hash.sync_lock)) {
|
||||
return ECL_T;
|
||||
}
|
||||
#endif
|
||||
return ECL_NIL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -369,6 +369,7 @@ struct ecl_hashtable_entry { /* hash table entry */
|
|||
struct ecl_hashtable { /* hash table header */
|
||||
_ECL_HDR2(test,weak);
|
||||
struct ecl_hashtable_entry *data; /* pointer to the hash table */
|
||||
cl_object sync_lock; /* synchronization lock */
|
||||
cl_index entries; /* number of entries */
|
||||
cl_index size; /* hash table size */
|
||||
cl_index limit; /* hash table threshold (integer value) */
|
||||
|
|
@ -378,6 +379,11 @@ struct ecl_hashtable { /* hash table header */
|
|||
cl_object (*get)(cl_object, cl_object, cl_object);
|
||||
cl_object (*set)(cl_object, cl_object, cl_object);
|
||||
bool (*rem)(cl_object, cl_object);
|
||||
/* Unsafe variants are used to store the real accessors when
|
||||
the synchronized variant is bound to get/set/rem. */
|
||||
cl_object (*get_unsafe)(cl_object, cl_object, cl_object);
|
||||
cl_object (*set_unsafe)(cl_object, cl_object, cl_object);
|
||||
bool (*rem_unsafe)(cl_object, cl_object);
|
||||
};
|
||||
|
||||
typedef enum { /* array element type */
|
||||
|
|
|
|||
|
|
@ -64,3 +64,9 @@
|
|||
|
||||
(test hash-tables.weak-err
|
||||
(signals simple-type-error (make-hash-table :weakness :whatever)))
|
||||
|
||||
|
||||
;;; Synchronization
|
||||
(test hash-tables.sync
|
||||
(let ((ht (make-hash-table :synchronized t)))
|
||||
(is-true (ext:hash-table-synchronized-p ht))))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue