diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 720afdf4dd110b0c176e16ee53b6939f913b4e7c..65168b164d51e9d3a3afb8dfdad2af171e94320f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1476,6 +1476,9 @@ virFirewallStartTransaction; # util/virhash.h virHashAddEntry; +virHashAtomicNew; +virHashAtomicSteal; +virHashAtomicUpdate; virHashCreate; virHashEqual; virHashForEach; diff --git a/src/util/virhash.c b/src/util/virhash.c index e3c1880fbfe00dec1518335213c7721c32d3cf41..3cfcc696afb5aa1df4b9ac0ceec0fb1fd7c2ff38 100644 --- a/src/util/virhash.c +++ b/src/util/virhash.c @@ -31,6 +31,7 @@ #include "virhashcode.h" #include "virrandom.h" #include "virstring.h" +#include "virobject.h" #define VIR_FROM_THIS VIR_FROM_NONE @@ -76,6 +77,28 @@ struct _virHashTable { virHashKeyFree keyFree; }; +struct _virHashAtomic { + virObjectLockable parent; + virHashTablePtr hash; +}; + +static virClassPtr virHashAtomicClass; +static void virHashAtomicDispose(void *obj); + +static int virHashAtomicOnceInit(void) +{ + virHashAtomicClass = virClassNew(virClassForObjectLockable(), + "virHashAtomic", + sizeof(virHashAtomic), + virHashAtomicDispose); + if (!virHashAtomicClass) + return -1; + else + return 0; +} +VIR_ONCE_GLOBAL_INIT(virHashAtomic) + + static uint32_t virHashStrCode(const void *name, uint32_t seed) { return virHashCodeGen(name, strlen(name), seed); @@ -178,6 +201,36 @@ virHashTablePtr virHashCreate(ssize_t size, virHashDataFree dataFree) virHashStrFree); } + +virHashAtomicPtr +virHashAtomicNew(ssize_t size, + virHashDataFree dataFree) +{ + virHashAtomicPtr hash; + + if (virHashAtomicInitialize() < 0) + return NULL; + + if (!(hash = virObjectLockableNew(virHashAtomicClass))) + return NULL; + + if (!(hash->hash = virHashCreate(size, dataFree))) { + virObjectUnref(hash); + return NULL; + } + return hash; +} + + +static void +virHashAtomicDispose(void *obj) +{ + virHashAtomicPtr hash = obj; + + virHashFree(hash->hash); +} + + /** * virHashGrow: * @table: the hash table @@ -360,6 +413,21 @@ virHashUpdateEntry(virHashTablePtr table, const void *name, return virHashAddOrUpdateEntry(table, name, userdata, true); } +int +virHashAtomicUpdate(virHashAtomicPtr table, + const void *name, + void *userdata) +{ + int ret; + + virObjectLock(table); + ret = virHashAddOrUpdateEntry(table->hash, name, userdata, true); + virObjectUnlock(table); + + return ret; +} + + /** * virHashLookup: * @table: the hash table @@ -409,6 +477,19 @@ void *virHashSteal(virHashTablePtr table, const void *name) return data; } +void * +virHashAtomicSteal(virHashAtomicPtr table, + const void *name) +{ + void *data; + + virObjectLock(table); + data = virHashSteal(table->hash, name); + virObjectUnlock(table); + + return data; +} + /** * virHashSize: diff --git a/src/util/virhash.h b/src/util/virhash.h index a1371373c93a6bfd8ce412f6ba24d7ab13f5c7c5..50b9a04883122e187ccdbfb698f7d1d74025d6cc 100644 --- a/src/util/virhash.h +++ b/src/util/virhash.h @@ -21,6 +21,9 @@ typedef struct _virHashTable virHashTable; typedef virHashTable *virHashTablePtr; +typedef struct _virHashAtomic virHashAtomic; +typedef virHashAtomic *virHashAtomicPtr; + /* * function types: */ @@ -101,6 +104,8 @@ typedef void (*virHashKeyFree)(void *name); */ virHashTablePtr virHashCreate(ssize_t size, virHashDataFree dataFree); +virHashAtomicPtr virHashAtomicNew(ssize_t size, + virHashDataFree dataFree); virHashTablePtr virHashCreateFull(ssize_t size, virHashDataFree dataFree, virHashKeyCode keyCode, @@ -119,6 +124,9 @@ int virHashAddEntry(virHashTablePtr table, int virHashUpdateEntry(virHashTablePtr table, const void *name, void *userdata); +int virHashAtomicUpdate(virHashAtomicPtr table, + const void *name, + void *userdata); /* * Remove an entry from the hash table. @@ -140,6 +148,8 @@ void *virHashLookup(const virHashTable *table, const void *name); * Retrieve & remove the userdata. */ void *virHashSteal(virHashTablePtr table, const void *name); +void *virHashAtomicSteal(virHashAtomicPtr table, + const void *name); /* * Get the hash table's key/value pairs and have them optionally sorted.