34 #define REFOBJ_MAGIC 0xdeadc0de
119 #define refobj_offset sizeof(struct ref_obj);
136 if ((robj = malloc(asize))) {
137 memset(robj, 0, asize);
139 pthread_mutex_init(&ref->
lock, NULL);
166 if (!pthread_mutex_lock(&ref->
lock)) {
171 pthread_mutex_unlock(&ref->
lock);
197 pthread_mutex_lock(&ref->
lock);
208 pthread_mutex_unlock(&ref->
lock);
209 pthread_mutex_destroy(&ref->
lock);
212 pthread_mutex_unlock(&ref->
lock);
235 pthread_mutex_lock(&ref->
lock);
237 pthread_mutex_unlock(&ref->
lock);
259 pthread_mutex_lock(&ref->
lock);
261 pthread_mutex_unlock(&ref->
lock);
277 pthread_mutex_lock(&ref->
lock);
293 return ((pthread_mutex_trylock(&ref->
lock)) ? -1 : 0);
309 pthread_mutex_unlock(&ref->
lock);
314 static void empty_buckets(
void *
data) {
331 int len = strlen(orig) + 1;
335 memcpy(nobj, orig, len);
358 short int buckets, cnt;
360 buckets = (1 << bitmask);
363 if (!(
new =
objalloc(
sizeof(*
new) + (
sizeof(
void *) +
sizeof(pthread_mutex_t) +
sizeof(
size_t)) * buckets, empty_buckets))) {
369 new->list = (
void *)((
char *)
new +
sizeof(*new));
370 for (cnt = 0; cnt < buckets; cnt++) {
371 if ((new->list[cnt] = malloc(
sizeof(*new->list[cnt])))) {
372 memset(new->list[cnt], 0,
sizeof(*new->list[cnt]));
377 new->locks = (
void *)&new->list[buckets];
378 for (cnt = 0; cnt < buckets; cnt++) {
379 pthread_mutex_init(&new->locks[cnt], NULL);
383 new->version = (
void *)&new->locks[buckets];
385 new->hash_func = hash_function;
393 if ((hash << bucketbits) < 0) {
398 while (lhead && lhead->
next && (lhead->
next->
hash < hash)) {
406 static int gethash(
struct bucket_list *blist,
const void *data,
int key) {
407 const char *ptr =
data;
432 unsigned int hash, bucket;
446 hash = gethash(blist, data, 0);
449 pthread_mutex_lock(&blist->
locks[bucket]);
450 lhead = blist->
list[bucket];
452 if (!lhead || lhead->
prev) {
453 if (!(tmp = malloc(
sizeof(*tmp)))) {
454 pthread_mutex_unlock(&blist->
locks[bucket]);
459 memset(tmp, 0,
sizeof(*tmp));
465 blist->
list[bucket] = tmp;
469 }
else if (hash < lhead->hash) {
473 blist->
list[bucket] = tmp;
475 }
else if (hash > lhead->
prev->
hash) {
482 lhead = blist_gotohash(lhead, hash, blist->
bucketbits);
502 pthread_mutex_unlock(&blist->
locks[bucket]);
521 hash = gethash(blist, data, 0);
524 pthread_mutex_lock(&blist->
locks[bucket]);
525 entry = blist_gotohash(blist->
list[bucket], hash + 1, blist->
bucketbits);
526 if (entry && entry->
hash == hash) {
527 if (entry->
next && (entry == blist->
list[bucket])) {
530 }
else if (entry->
next) {
533 }
else if (entry == blist->
list[bucket]) {
534 blist->
list[bucket] = NULL;
546 pthread_mutex_unlock(&blist->
locks[bucket]);
580 hash = gethash(blist, key, 1);
583 pthread_mutex_lock(&blist->
locks[bucket]);
584 entry = blist_gotohash(blist->
list[bucket], hash + 1, blist->
bucketbits);
585 if (entry && entry->
data) {
589 pthread_mutex_unlock(&blist->
locks[bucket]);
593 pthread_mutex_unlock(&blist->
locks[bucket]);
595 if (entry->
data && (entry->
hash == hash)) {
617 if (!blist || !callback) {
623 callback(data, data2);
629 static void free_bloop(
void *data) {
643 if (blist && (bloop =
objalloc(
sizeof(*bloop), free_bloop))) {
653 pthread_mutex_unlock(&blist->
locks[bloop->
bucket]);
678 pthread_mutex_unlock(&blist->
locks[bloop->
bucket]);
691 data = (entry) ? entry->
data : NULL;
697 pthread_mutex_unlock(&blist->
locks[bloop->
bucket]);
712 int bucket = bloop->
bucket;
719 pthread_mutex_unlock(&blist->
locks[bucket]);
725 pthread_mutex_unlock(&blist->
locks[bucket]);
735 }
else if (bloop->
cur == blist->
list[bucket]) {
736 blist->
list[bucket] = NULL;
748 pthread_mutex_unlock(&blist->
locks[bucket]);
#define refobj_offset
The size of ref_obj is the offset for the data.
void * create_bucketlist(int bitmask, blisthash hash_function)
struct blist_obj ** list
Array of blist_obj one per bucket ie 2^bucketbits.
int objref(void *data)
Reference a object.
blisthash hash_func
Hash function called to calculate the hash and thus the bucket its placed in.
uint32_t head_hash
Hash of head if we need to comeback.
unsigned short bucket
Active bucket as determined by hash.
int objlock(void *data)
Lock the reference.
void * objchar(const char *orig)
Return a reference to copy of a buffer.
int32_t hash
Hash value calculated from the data.
void * objalloc(int size, objdestroy)
Allocate a referenced lockable object.
struct blist_obj * head
Current bucket.
int bucket_list_cnt(struct bucket_list *blist)
Return number of items in the list.
int objcnt(void *data)
Return current reference count.
void * next_bucket_loop(struct bucket_loop *bloop)
Return a reference to the next item in the list this could be the first item.
size_t count
Number of items held.
struct blist_obj * cur
Current item.
void(* objdestroy)(void *)
Callback used to clean data of a reference object when it is to be freed.
objdestroy destroy
Function to call to clean up the data before its freed.
DTS Application library API Include file.
size_t * version
version of the bucket to detect changes during iteration (loop)
int objtrylock(void *data)
Try lock a reference.
Internal structure of all referenced objects.
struct blist_obj * prev
Previous entry in the bucket.
void * data
Pointer to the data referenced.
size_t version
Our version check this with blist to determine if we must rewined and fast forward.
#define REFOBJ_MAGIC
Magic number stored as first field of all referenced objects.
size_t size
The size allocated to this object.
int objunlock(void *data)
Unlock a reference.
uint32_t magic
Memory integrity check used to prevent non refeferenced objects been handled as referenced objects...
struct blist_obj * next
Next entry in the bucket.
void(* blist_cb)(void *, void *)
This callback is run on each entry in a list.
uint32_t cnt
Reference count the oject will be freed when the reference count reaches 0.
void bucketlist_callback(struct bucket_list *blist, blist_cb callback, void *data2)
Run a callback function on all items in the list.
#define jenhash(key, length, initval)
Define jenhash as hashlittle on big endian it should be hashbig.
struct bucket_list * blist
Referenece to the bucket been itereated.
void remove_bucket_loop(struct bucket_loop *bloop)
Safely remove a item from a list while iterating in a loop.
pthread_mutex_t * locks
Array of locks one per bucket.
unsigned short bucketbits
number of buckets 2^n
int objsize(void *data)
Size requested for data.
uint32_t cur_hash
Hash of cur if we need to comeback.
int addtobucket(struct bucket_list *blist, void *data)
Add a reference to the bucketlist.
void * bucket_list_find_key(struct bucket_list *list, const void *key)
Find and return a reference to a item matching supplied key.
void remove_bucket_item(struct bucket_list *blist, void *data)
Remove and unreference a item from the list.
int objunref(void *data)
Drop reference held.
struct ref_obj * data
Reference to data held.
int32_t(* blisthash)(const void *, int)
Callback used to calculate the hash of a structure.
struct bucket_loop * init_bucket_loop(struct bucket_list *blist)
Create a bucket list iterator to safely iterate the list.
pthread_mutex_t lock
this is a pointer to the lock it may be changed to be the lock
Bucket list, hold hashed objects in buckets.