DTS Application Library  0.2.3
Application library containing referenced objects and interfaces to common libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
Hashed bucket linked lists of referenced objects

Store references in and retrive from linked lists based on a hash. More...

Files

file  refobj.c
 Referenced Lockable Objects.
 

Data Structures

struct  blist_obj
 Entry in a bucket list. More...
 
struct  bucket_list
 Bucket list, hold hashed objects in buckets. More...
 
struct  bucket_loop
 Bucket iterator. More...
 

Typedefs

typedef int32_t(* blisthash )(const void *, int)
 Callback used to calculate the hash of a structure. More...
 
typedef void(* blist_cb )(void *, void *)
 This callback is run on each entry in a list. More...
 

Functions

void * create_bucketlist (int bitmask, blisthash hash_function)
 
int addtobucket (struct bucket_list *blist, void *data)
 Add a reference to the bucketlist. More...
 
void remove_bucket_item (struct bucket_list *blist, void *data)
 Remove and unreference a item from the list. More...
 
int bucket_list_cnt (struct bucket_list *blist)
 Return number of items in the list. More...
 
void * bucket_list_find_key (struct bucket_list *blist, const void *key)
 Find and return a reference to a item matching supplied key. More...
 
void bucketlist_callback (struct bucket_list *blist, blist_cb callback, void *data2)
 Run a callback function on all items in the list. More...
 
struct bucket_loopinit_bucket_loop (struct bucket_list *blist)
 Create a bucket list iterator to safely iterate the list. More...
 
void * next_bucket_loop (struct bucket_loop *bloop)
 Return a reference to the next item in the list this could be the first item. More...
 
void remove_bucket_loop (struct bucket_loop *bloop)
 Safely remove a item from a list while iterating in a loop. More...
 

Detailed Description

Store references in and retrive from linked lists based on a hash.

Create a hashed bucket list.

See Also
Hashed Bucket Lists
Burtle Bob hash algorythim.

A bucket list is a ref obj the "list" element is a array of "bucket" entries each has a hash the default is to hash the memory when there is no call back

Todo:
Dont hash the memory supply a key perhaps a key array type.
Warning
the hash must be calculated on immutable data.
Note
a bucket list should only contain objects of the same type.
Unreferencing the bucketlist will cause it to be emptied and freed when the count reaches 0.
See Also
blisthash
Parameters
bitmaskNumber of buckets to create 2^bitmask.
hash_functionCallback that returns the unique hash for a item this value must not change.
Returns
Reference to a empty bucket list.

Typedef Documentation

typedef void(* blist_cb)(void *, void *)

This callback is run on each entry in a list.

See Also
bucketlist_callback()
Parameters
dataReference held by the list.
data2Reference to data supplied when calling bucketlist_callback.

Definition at line 278 of file dtsapp.h.

typedef int32_t(* blisthash)(const void *, int)

Callback used to calculate the hash of a structure.

Parameters
dataData or key to calculate hash from.
keyKey if set to non zero data supplied is the key not data.
Returns
Hash for the Reference.

Definition at line 271 of file dtsapp.h.

Function Documentation

int addtobucket ( struct bucket_list blist,
void *  data 
)

Add a reference to the bucketlist.

Create a entry in the list for reference obtained from data.

Parameters
blistBucket list to add too.
datato obtain a reference too and add to the list.
Returns
0 on failure 1 on success.

Definition at line 428 of file refobj.c.

References bucket_list::bucketbits, bucket_list::count, ref_obj::data, blist_obj::data, blist_obj::hash, bucket_list::list, bucket_list::locks, blist_obj::next, objlock(), objref(), objunlock(), objunref(), blist_obj::prev, refobj_offset, and bucket_list::version.

Referenced by add_radserver(), framework_mkthread(), process_config(), rfc6296_map_add(), and xslt_addparam().

428  {
429  char *ptr = data;
430  struct ref_obj *ref;
431  struct blist_obj *lhead, *tmp;
432  unsigned int hash, bucket;
433 
434  if (!objref(blist)) {
435  return (0);
436  }
437 
438  if (!objref(data)) {
439  objunref(blist);
440  return (0);
441  }
442 
443  ptr = ptr - refobj_offset;
444  ref = (struct ref_obj *)ptr;
445 
446  hash = gethash(blist, data, 0);
447  bucket = ((hash >> (32 - blist->bucketbits)) & ((1 << blist->bucketbits) - 1));
448 
449  pthread_mutex_lock(&blist->locks[bucket]);
450  lhead = blist->list[bucket];
451  /*no head or non null head*/
452  if (!lhead || lhead->prev) {
453  if (!(tmp = malloc(sizeof(*tmp)))) {
454  pthread_mutex_unlock(&blist->locks[bucket]);
455  objunref(data);
456  objunref(blist);
457  return (0);
458  }
459  memset(tmp, 0, sizeof(*tmp));
460  tmp->hash = hash;
461  tmp->data = ref;
462 
463  /*there is no head*/
464  if (!lhead) {
465  blist->list[bucket] = tmp;
466  tmp->prev = tmp;
467  tmp->next = NULL;
468  /*become new head*/
469  } else if (hash < lhead->hash) {
470  tmp->next = lhead;
471  tmp->prev = lhead->prev;
472  lhead->prev = tmp;
473  blist->list[bucket] = tmp;
474  /*new tail*/
475  } else if (hash > lhead->prev->hash) {
476  tmp->prev = lhead->prev;
477  tmp->next = NULL;
478  lhead->prev->next = tmp;
479  lhead->prev = tmp;
480  /*insert entry*/
481  } else {
482  lhead = blist_gotohash(lhead, hash, blist->bucketbits);
483  tmp->next = lhead->next;
484  tmp->prev = lhead;
485 
486  if (lhead->next) {
487  lhead->next->prev = tmp;
488  } else {
489  blist->list[bucket]->prev = tmp;
490  }
491  lhead->next = tmp;
492  }
493  } else {
494  /*set NULL head*/
495  lhead->data = ref;
496  lhead->prev = lhead;
497  lhead->next = NULL;
498  lhead->hash = hash;
499  }
500 
501  blist->version[bucket]++;
502  pthread_mutex_unlock(&blist->locks[bucket]);
503 
504  objlock(blist);
505  blist->count++;
506  objunlock(blist);
507  objunref(blist);
508 
509  return (1);
510 }
#define refobj_offset
The size of ref_obj is the offset for the data.
Definition: refobj.c:119
struct blist_obj ** list
Array of blist_obj one per bucket ie 2^bucketbits.
Definition: refobj.c:83
int objref(void *data)
Reference a object.
Definition: refobj.c:153
int objlock(void *data)
Lock the reference.
Definition: refobj.c:269
int32_t hash
Hash value calculated from the data.
Definition: refobj.c:64
Entry in a bucket list.
Definition: refobj.c:61
size_t count
Number of items held.
Definition: refobj.c:79
size_t * version
version of the bucket to detect changes during iteration (loop)
Definition: refobj.c:87
Internal structure of all referenced objects.
Definition: refobj.c:38
struct blist_obj * prev
Previous entry in the bucket.
Definition: refobj.c:68
void * data
Pointer to the data referenced.
Definition: refobj.c:54
int objunlock(void *data)
Unlock a reference.
Definition: refobj.c:301
struct blist_obj * next
Next entry in the bucket.
Definition: refobj.c:66
pthread_mutex_t * locks
Array of locks one per bucket.
Definition: refobj.c:85
unsigned short bucketbits
number of buckets 2^n
Definition: refobj.c:77
int objunref(void *data)
Drop reference held.
Definition: refobj.c:184
struct ref_obj * data
Reference to data held.
Definition: refobj.c:70
int bucket_list_cnt ( struct bucket_list blist)

Return number of items in the list.

Parameters
blistBucket list to get count of.
Returns
Total number of items in all buckets.

Definition at line 552 of file refobj.c.

References bucket_list::count, objlock(), and objunlock().

Referenced by add_radserver(), ldap_doadd(), and ldap_domodify().

552  {
553  int ret = -1;
554 
555  if (blist) {
556  objlock(blist);
557  ret = blist->count;
558  objunlock(blist);
559  }
560  return (ret);
561 }
int objlock(void *data)
Lock the reference.
Definition: refobj.c:269
size_t count
Number of items held.
Definition: refobj.c:79
int objunlock(void *data)
Unlock a reference.
Definition: refobj.c:301
void* bucket_list_find_key ( struct bucket_list blist,
const void *  key 
)

Find and return a reference to a item matching supplied key.

The key is supplied to the hash callback ad the data value and the key flag set. The hash for the object will be returned by the hash callback to find the item in the lists.

Note
if the hash is not calculated equal to the original value it wont be found.
Parameters
blistBucket list to search.
keySupplied to hash callback to find the item.
Returns
New reference to the found item that needs to be unreferenced or NULL.

Definition at line 572 of file refobj.c.

References bucket_list::bucketbits, ref_obj::data, blist_obj::data, blist_obj::hash, bucket_list::list, bucket_list::locks, objref(), and objunref().

Referenced by get_config_category(), get_config_entry(), get_config_file(), ldap_getattr(), ldap_getentry(), nfqueue_attach(), xml_getattr(), and xml_getnode().

572  {
573  struct blist_obj *entry;
574  int hash, bucket;
575 
576  if (!blist) {
577  return (NULL);
578  }
579 
580  hash = gethash(blist, key, 1);
581  bucket = ((hash >> (32 - blist->bucketbits)) & ((1 << blist->bucketbits) - 1));
582 
583  pthread_mutex_lock(&blist->locks[bucket]);
584  entry = blist_gotohash(blist->list[bucket], hash + 1, blist->bucketbits);
585  if (entry && entry->data) {
586  objref(entry->data->data);
587  } else
588  if (!entry) {
589  pthread_mutex_unlock(&blist->locks[bucket]);
590  return NULL;
591  }
592 
593  pthread_mutex_unlock(&blist->locks[bucket]);
594 
595  if (entry->data && (entry->hash == hash)) {
596  return (entry->data->data);
597  } else
598  if (entry->data) {
599  objunref(entry->data->data);
600  }
601 
602  return NULL;
603 }
struct blist_obj ** list
Array of blist_obj one per bucket ie 2^bucketbits.
Definition: refobj.c:83
int objref(void *data)
Reference a object.
Definition: refobj.c:153
int32_t hash
Hash value calculated from the data.
Definition: refobj.c:64
Entry in a bucket list.
Definition: refobj.c:61
void * data
Pointer to the data referenced.
Definition: refobj.c:54
pthread_mutex_t * locks
Array of locks one per bucket.
Definition: refobj.c:85
unsigned short bucketbits
number of buckets 2^n
Definition: refobj.c:77
int objunref(void *data)
Drop reference held.
Definition: refobj.c:184
struct ref_obj * data
Reference to data held.
Definition: refobj.c:70
void bucketlist_callback ( struct bucket_list blist,
blist_cb  callback,
void *  data2 
)

Run a callback function on all items in the list.

This will iterate safely through all items calling the callback with the item and the optional data supplied.

See Also
blist_cb
Parameters
blistBucket list to iterate through.
callbackCallback to call for each iteration.
data2Data to be set as option to the callback.

Definition at line 613 of file refobj.c.

References init_bucket_loop(), next_bucket_loop(), and objunref().

Referenced by config_cat_callback(), config_entry_callback(), config_file_callback(), and rfc6296_test().

613  {
614  struct bucket_loop *bloop;
615  void *data;
616 
617  if (!blist || !callback) {
618  return;
619  }
620 
621  bloop = init_bucket_loop(blist);
622  while(blist && bloop && (data = next_bucket_loop(bloop))) {
623  callback(data, data2);
624  objunref(data);
625  }
626  objunref(bloop);
627 }
Bucket iterator.
Definition: refobj.c:97
void * next_bucket_loop(struct bucket_loop *bloop)
Return a reference to the next item in the list this could be the first item.
Definition: refobj.c:662
int objunref(void *data)
Drop reference held.
Definition: refobj.c:184
struct bucket_loop * init_bucket_loop(struct bucket_list *blist)
Create a bucket list iterator to safely iterate the list.
Definition: refobj.c:640
void* create_bucketlist ( int  bitmask,
blisthash  hash_function 
)

Definition at line 356 of file refobj.c.

References bucket_list::bucketbits, and objalloc().

Referenced by add_radserver(), ldap_addinit(), ldap_modifyinit(), rfc6296_map_add(), socketserver(), startthreads(), xslt_clearparam(), and xslt_open().

356  {
357  struct bucket_list *new;
358  short int buckets, cnt;
359 
360  buckets = (1 << bitmask);
361 
362  /* allocate session bucket list memory size of the struct plus a list lock and version for each bucket*/
363  if (!(new = objalloc(sizeof(*new) + (sizeof(void *) + sizeof(pthread_mutex_t) + sizeof(size_t)) * buckets, empty_buckets))) {
364  return NULL;
365  }
366 
367  /*initialise each bucket*/
368  new->bucketbits = bitmask;
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]));
373  }
374  }
375 
376  /*next pointer is pointer to locks*/
377  new->locks = (void *)&new->list[buckets];
378  for (cnt = 0; cnt < buckets; cnt++) {
379  pthread_mutex_init(&new->locks[cnt], NULL);
380  }
381 
382  /*Next up version array*/
383  new->version = (void *)&new->locks[buckets];
384 
385  new->hash_func = hash_function;
386 
387  return (new);
388 }
void * objalloc(int size, objdestroy)
Allocate a referenced lockable object.
Definition: refobj.c:129
unsigned short bucketbits
number of buckets 2^n
Definition: refobj.c:77
Bucket list, hold hashed objects in buckets.
Definition: refobj.c:75
struct bucket_loop* init_bucket_loop ( struct bucket_list blist)

Create a bucket list iterator to safely iterate the list.

Parameters
blistBucket list to create iterator for.
Returns
Bucket list iterator that needs to be unreferenced when completed.

Definition at line 640 of file refobj.c.

References bucket_loop::blist, bucket_loop::bucket, blist_obj::hash, bucket_loop::head, bucket_loop::head_hash, bucket_list::list, bucket_list::locks, objalloc(), objref(), bucket_list::version, and bucket_loop::version.

Referenced by bucketlist_callback(), get_category_loop(), ldap_doadd(), and ldap_domodify().

640  {
641  struct bucket_loop *bloop = NULL;
642 
643  if (blist && (bloop = objalloc(sizeof(*bloop), free_bloop))) {
644  objref(blist);
645  bloop->blist = blist;
646  bloop->bucket = 0;
647  pthread_mutex_lock(&blist->locks[bloop->bucket]);
648  bloop->head = blist->list[0];
649  if (bloop->head) {
650  bloop->head_hash = bloop->head->hash;
651  };
652  bloop->version = blist->version[0];
653  pthread_mutex_unlock(&blist->locks[bloop->bucket]);
654  }
655 
656  return (bloop);
657 }
Bucket iterator.
Definition: refobj.c:97
struct blist_obj ** list
Array of blist_obj one per bucket ie 2^bucketbits.
Definition: refobj.c:83
int objref(void *data)
Reference a object.
Definition: refobj.c:153
uint32_t head_hash
Hash of head if we need to comeback.
Definition: refobj.c:106
unsigned short bucket
Active bucket as determined by hash.
Definition: refobj.c:101
int32_t hash
Hash value calculated from the data.
Definition: refobj.c:64
void * objalloc(int size, objdestroy)
Allocate a referenced lockable object.
Definition: refobj.c:129
struct blist_obj * head
Current bucket.
Definition: refobj.c:110
size_t * version
version of the bucket to detect changes during iteration (loop)
Definition: refobj.c:87
size_t version
Our version check this with blist to determine if we must rewined and fast forward.
Definition: refobj.c:104
struct bucket_list * blist
Referenece to the bucket been itereated.
Definition: refobj.c:99
pthread_mutex_t * locks
Array of locks one per bucket.
Definition: refobj.c:85
void* next_bucket_loop ( struct bucket_loop bloop)

Return a reference to the next item in the list this could be the first item.

Parameters
bloopBucket iterator
Returns
Next available item or NULL when there no items left

Definition at line 662 of file refobj.c.

References bucket_loop::blist, bucket_loop::bucket, bucket_list::bucketbits, bucket_loop::cur, bucket_loop::cur_hash, ref_obj::data, blist_obj::data, blist_obj::hash, bucket_loop::head, bucket_loop::head_hash, bucket_list::list, bucket_list::locks, blist_obj::next, objref(), blist_obj::prev, bucket_list::version, and bucket_loop::version.

Referenced by bucketlist_callback(), get_category_next(), ldap_doadd(), and ldap_domodify().

662  {
663  struct bucket_list *blist = bloop->blist;
664  struct ref_obj *entry = NULL;
665  void *data = NULL;
666 
667  pthread_mutex_lock(&blist->locks[bloop->bucket]);
668  if (bloop->head_hash && (blist->version[bloop->bucket] != bloop->version)) {
669  /* bucket has changed unexpectedly i need to ff/rew to hash*/
670  bloop->head = blist_gotohash(blist->list[bloop->bucket], bloop->head_hash + 1, blist->bucketbits);
671  /*if head has gone find next suitable ignore any added*/
672  while (bloop->head && (bloop->head->hash < bloop->head_hash)) {
673  bloop->head = bloop->head->next;
674  }
675  }
676 
677  while (!bloop->head || !bloop->head->prev) {
678  pthread_mutex_unlock(&blist->locks[bloop->bucket]);
679  bloop->bucket++;
680  if (bloop->bucket < (1 << blist->bucketbits)) {
681  pthread_mutex_lock(&blist->locks[bloop->bucket]);
682  bloop->head = blist->list[bloop->bucket];
683  } else {
684  return NULL;
685  }
686  }
687 
688  if (bloop->head) {
689  bloop->cur = bloop->head;
690  entry = (bloop->head->data) ? bloop->head->data : NULL;
691  data = (entry) ? entry->data : NULL;
692  objref(data);
693  bloop->head = bloop->head->next;
694  bloop->head_hash = (bloop->head) ? bloop->head->hash : 0;
695  bloop->cur_hash = (bloop->cur) ? bloop->cur->hash : 0;
696  }
697  pthread_mutex_unlock(&blist->locks[bloop->bucket]);
698 
699  return (data);
700 }
struct blist_obj ** list
Array of blist_obj one per bucket ie 2^bucketbits.
Definition: refobj.c:83
int objref(void *data)
Reference a object.
Definition: refobj.c:153
uint32_t head_hash
Hash of head if we need to comeback.
Definition: refobj.c:106
unsigned short bucket
Active bucket as determined by hash.
Definition: refobj.c:101
int32_t hash
Hash value calculated from the data.
Definition: refobj.c:64
struct blist_obj * head
Current bucket.
Definition: refobj.c:110
struct blist_obj * cur
Current item.
Definition: refobj.c:112
size_t * version
version of the bucket to detect changes during iteration (loop)
Definition: refobj.c:87
Internal structure of all referenced objects.
Definition: refobj.c:38
struct blist_obj * prev
Previous entry in the bucket.
Definition: refobj.c:68
void * data
Pointer to the data referenced.
Definition: refobj.c:54
size_t version
Our version check this with blist to determine if we must rewined and fast forward.
Definition: refobj.c:104
struct blist_obj * next
Next entry in the bucket.
Definition: refobj.c:66
struct bucket_list * blist
Referenece to the bucket been itereated.
Definition: refobj.c:99
pthread_mutex_t * locks
Array of locks one per bucket.
Definition: refobj.c:85
unsigned short bucketbits
number of buckets 2^n
Definition: refobj.c:77
uint32_t cur_hash
Hash of cur if we need to comeback.
Definition: refobj.c:108
struct ref_obj * data
Reference to data held.
Definition: refobj.c:70
Bucket list, hold hashed objects in buckets.
Definition: refobj.c:75
void remove_bucket_item ( struct bucket_list blist,
void *  data 
)

Remove and unreference a item from the list.

Note
Dont use this function directly during iteration as it imposes performance penalties.
Parameters
blistBucket list to remove item from.
See Also
remove_bucket_loop
Parameters
dataReference to be removed and unreferenced.

Definition at line 517 of file refobj.c.

References bucket_list::bucketbits, bucket_list::count, ref_obj::data, blist_obj::data, blist_obj::hash, bucket_list::list, bucket_list::locks, blist_obj::next, objlock(), objunlock(), objunref(), blist_obj::prev, and bucket_list::version.

Referenced by ldap_unref_attr(), and ldap_unref_entry().

517  {
518  struct blist_obj *entry;
519  int hash, bucket;
520 
521  hash = gethash(blist, data, 0);
522  bucket = ((hash >> (32 - blist->bucketbits)) & ((1 << blist->bucketbits) - 1));
523 
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])) {
528  entry->next->prev = entry->prev;
529  blist->list[bucket] = entry->next;
530  } else if (entry->next) {
531  entry->next->prev = entry->prev;
532  entry->prev->next = entry->next;
533  } else if (entry == blist->list[bucket]) {
534  blist->list[bucket] = NULL;
535  } else {
536  entry->prev->next = NULL;
537  blist->list[bucket]->prev = entry->prev;
538  }
539  objunref(entry->data->data);
540  free(entry);
541  objlock(blist);
542  blist->count--;
543  blist->version[bucket]++;
544  objunlock(blist);
545  }
546  pthread_mutex_unlock(&blist->locks[bucket]);
547 }
struct blist_obj ** list
Array of blist_obj one per bucket ie 2^bucketbits.
Definition: refobj.c:83
int objlock(void *data)
Lock the reference.
Definition: refobj.c:269
int32_t hash
Hash value calculated from the data.
Definition: refobj.c:64
Entry in a bucket list.
Definition: refobj.c:61
size_t count
Number of items held.
Definition: refobj.c:79
size_t * version
version of the bucket to detect changes during iteration (loop)
Definition: refobj.c:87
struct blist_obj * prev
Previous entry in the bucket.
Definition: refobj.c:68
void * data
Pointer to the data referenced.
Definition: refobj.c:54
int objunlock(void *data)
Unlock a reference.
Definition: refobj.c:301
struct blist_obj * next
Next entry in the bucket.
Definition: refobj.c:66
pthread_mutex_t * locks
Array of locks one per bucket.
Definition: refobj.c:85
unsigned short bucketbits
number of buckets 2^n
Definition: refobj.c:77
int objunref(void *data)
Drop reference held.
Definition: refobj.c:184
struct ref_obj * data
Reference to data held.
Definition: refobj.c:70
void remove_bucket_loop ( struct bucket_loop bloop)

Safely remove a item from a list while iterating in a loop.

While traversing the bucket list its best to use this function to remove a reference and delete it from the list.

Note
Removeing a item from the list without using this function will cause the the version to change and the iterator to rewind and fast forward.
Parameters
bloopBucket iterator.

Definition at line 710 of file refobj.c.

References bucket_loop::blist, bucket_loop::bucket, bucket_list::bucketbits, bucket_list::count, bucket_loop::cur, bucket_loop::cur_hash, ref_obj::data, blist_obj::data, blist_obj::hash, bucket_list::list, bucket_list::locks, blist_obj::next, objlock(), objunlock(), objunref(), blist_obj::prev, bucket_list::version, and bucket_loop::version.

710  {
711  struct bucket_list *blist = bloop->blist;
712  int bucket = bloop->bucket;
713 
714  pthread_mutex_lock(&blist->locks[bloop->bucket]);
715  /*if the bucket has altered need to verify i can remove*/
716  if (bloop->cur_hash && (!bloop->cur || (blist->version[bloop->bucket] != bloop->version))) {
717  bloop->cur = blist_gotohash(blist->list[bloop->bucket], bloop->cur_hash + 1, blist->bucketbits);
718  if (!bloop->cur || (bloop->cur->hash != bloop->cur_hash)) {
719  pthread_mutex_unlock(&blist->locks[bucket]);
720  return;
721  }
722  }
723 
724  if (!bloop->cur) {
725  pthread_mutex_unlock(&blist->locks[bucket]);
726  return;
727  }
728 
729  if (bloop->cur->next && (bloop->cur == blist->list[bucket])) {
730  bloop->cur->next->prev = bloop->cur->prev;
731  blist->list[bucket] = bloop->cur->next;
732  } else if (bloop->cur->next) {
733  bloop->cur->next->prev = bloop->cur->prev;
734  bloop->cur->prev->next = bloop->cur->next;
735  } else if (bloop->cur == blist->list[bucket]) {
736  blist->list[bucket] = NULL;
737  } else {
738  bloop->cur->prev->next = NULL;
739  blist->list[bucket]->prev = bloop->cur->prev;
740  }
741 
742  objunref(bloop->cur->data->data);
743  free(bloop->cur);
744  bloop->cur_hash = 0;
745  bloop->cur = NULL;
746  blist->version[bucket]++;
747  bloop->version++;
748  pthread_mutex_unlock(&blist->locks[bucket]);
749 
750  objlock(blist);
751  blist->count--;
752  objunlock(blist);
753 }
struct blist_obj ** list
Array of blist_obj one per bucket ie 2^bucketbits.
Definition: refobj.c:83
unsigned short bucket
Active bucket as determined by hash.
Definition: refobj.c:101
int objlock(void *data)
Lock the reference.
Definition: refobj.c:269
int32_t hash
Hash value calculated from the data.
Definition: refobj.c:64
size_t count
Number of items held.
Definition: refobj.c:79
struct blist_obj * cur
Current item.
Definition: refobj.c:112
size_t * version
version of the bucket to detect changes during iteration (loop)
Definition: refobj.c:87
struct blist_obj * prev
Previous entry in the bucket.
Definition: refobj.c:68
void * data
Pointer to the data referenced.
Definition: refobj.c:54
size_t version
Our version check this with blist to determine if we must rewined and fast forward.
Definition: refobj.c:104
int objunlock(void *data)
Unlock a reference.
Definition: refobj.c:301
struct blist_obj * next
Next entry in the bucket.
Definition: refobj.c:66
struct bucket_list * blist
Referenece to the bucket been itereated.
Definition: refobj.c:99
pthread_mutex_t * locks
Array of locks one per bucket.
Definition: refobj.c:85
unsigned short bucketbits
number of buckets 2^n
Definition: refobj.c:77
uint32_t cur_hash
Hash of cur if we need to comeback.
Definition: refobj.c:108
int objunref(void *data)
Drop reference held.
Definition: refobj.c:184
struct ref_obj * data
Reference to data held.
Definition: refobj.c:70
Bucket list, hold hashed objects in buckets.
Definition: refobj.c:75