RTS API Documentation  1.10.11
Functions | Variables
switch_hashtable.c File Reference
#include "switch.h"
#include "private/switch_hashtable_private.h"
+ Include dependency graph for switch_hashtable.c:

Go to the source code of this file.

Functions

switch_status_t switch_create_hashtable (switch_hashtable_t **hp, unsigned int minsize, unsigned int(*hashf)(void *), int(*eqf)(void *, void *))
 
static int hashtable_expand (switch_hashtable_t *h)
 
unsigned int switch_hashtable_count (switch_hashtable_t *h)
 
static void * _switch_hashtable_remove (switch_hashtable_t *h, void *k, unsigned int hashvalue, unsigned int index)
 
int switch_hashtable_insert_destructor (switch_hashtable_t *h, void *k, void *v, hashtable_flag_t flags, hashtable_destructor_t destructor)
 
void * switch_hashtable_search (switch_hashtable_t *h, void *k)
 
void * switch_hashtable_remove (switch_hashtable_t *h, void *k)
 
void switch_hashtable_destroy (switch_hashtable_t **h)
 
switch_hashtable_iterator_tswitch_hashtable_next (switch_hashtable_iterator_t **iP)
 
switch_hashtable_iterator_tswitch_hashtable_first_iter (switch_hashtable_t *h, switch_hashtable_iterator_t *it)
 
void switch_hashtable_this_val (switch_hashtable_iterator_t *i, void *val)
 
void switch_hashtable_this (switch_hashtable_iterator_t *i, const void **key, switch_ssize_t *klen, void **val)
 

Variables

static const unsigned int primes []
 
const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0])
 
const float max_load_factor = 0.65f
 

Function Documentation

◆ _switch_hashtable_remove()

static void* _switch_hashtable_remove ( switch_hashtable_t h,
void *  k,
unsigned int  hashvalue,
unsigned int  index 
)
static

Definition at line 156 of file switch_hashtable.c.

References entry::destructor, switch_hashtable::entrycount, switch_hashtable::eqfn, entry::flags, freekey, entry::h, HASHTABLE_FLAG_FREE_KEY, HASHTABLE_FLAG_FREE_VALUE, index, entry::k, entry::next, SWITCH_DECLARE, switch_safe_free, switch_hashtable::table, and entry::v.

Referenced by switch_hashtable_insert_destructor(), and switch_hashtable_remove().

156  {
157  /* TODO: consider compacting the table when the load factor drops enough,
158  * or provide a 'compact' method. */
159 
160  struct entry *e;
161  struct entry **pE;
162  void *v;
163 
164 
165  pE = &(h->table[index]);
166  e = *pE;
167  while (NULL != e) {
168  /* Check hash value to short circuit heavier comparison */
169  if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
170  *pE = e->next;
171  h->entrycount--;
172  v = e->v;
173  if (e->flags & HASHTABLE_FLAG_FREE_KEY) {
174  freekey(e->k);
175  }
176  if (e->flags & HASHTABLE_FLAG_FREE_VALUE) {
177  switch_safe_free(e->v);
178  v = NULL;
179  } else if (e->destructor) {
180  e->destructor(e->v);
181  v = e->v = NULL;
182  }
183  switch_safe_free(e);
184  return v;
185  }
186  pE = &(e->next);
187  e = e->next;
188  }
189  return NULL;
190 }
unsigned int h
int index
Definition: switch_cJSON.h:160
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
int(* eqfn)(void *k1, void *k2)
hashtable_flag_t flags
#define freekey(X)
hashtable_destructor_t destructor
struct entry * next

◆ hashtable_expand()

static int hashtable_expand ( switch_hashtable_t h)
static

Definition at line 94 of file switch_hashtable.c.

References entry::h, index, indexFor(), switch_hashtable::loadlimit, memset(), entry::next, prime_table_length, switch_hashtable::primeindex, primes, SWITCH_DECLARE, switch_safe_free, switch_hashtable::table, and switch_hashtable::tablelength.

Referenced by switch_hashtable_insert_destructor().

95 {
96  /* Double the size of the table to accommodate more entries */
97  struct entry **newtable;
98  struct entry *e;
99  struct entry **pE;
100  unsigned int newsize, i, index;
101  /* Check we're not hitting max capacity */
102  if (h->primeindex == (prime_table_length - 1)) return 0;
103  newsize = primes[++(h->primeindex)];
104 
105  newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
106  if (NULL != newtable)
107  {
108  memset(newtable, 0, newsize * sizeof(struct entry *));
109  /* This algorithm is not 'stable'. ie. it reverses the list
110  * when it transfers entries between the tables */
111  for (i = 0; i < h->tablelength; i++) {
112  while (NULL != (e = h->table[i])) {
113  h->table[i] = e->next;
114  index = indexFor(newsize,e->h);
115  e->next = newtable[index];
116  newtable[index] = e;
117  }
118  }
120  h->table = newtable;
121  }
122  /* Plan B: realloc instead */
123  else
124  {
125  newtable = (struct entry **)
126  realloc(h->table, newsize * sizeof(struct entry *));
127  if (NULL == newtable) { (h->primeindex)--; return 0; }
128  h->table = newtable;
129  memset(newtable[h->tablelength], 0, newsize - h->tablelength);
130  for (i = 0; i < h->tablelength; i++) {
131  for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
132  index = indexFor(newsize,e->h);
133 
134  if (index == i) {
135  pE = &(e->next);
136  } else {
137  *pE = e->next;
138  e->next = newtable[index];
139  newtable[index] = e;
140  }
141  }
142  }
143  }
144  h->tablelength = newsize;
145  h->loadlimit = (unsigned int) ceil(newsize * max_load_factor);
146  return -1;
147 }
unsigned int h
const unsigned int prime_table_length
const float max_load_factor
static __inline__ unsigned int indexFor(unsigned int tablelength, unsigned int hashvalue)
int index
Definition: switch_cJSON.h:160
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
static const unsigned int primes[]
memset(buf, 0, buflen)
struct entry * next

◆ switch_create_hashtable()

switch_status_t switch_create_hashtable ( switch_hashtable_t **  hp,
unsigned int  minsize,
unsigned int(*)(void *)  hashf,
int(*)(void *, void *)  eqf 
)

Definition at line 56 of file switch_hashtable.c.

References switch_hashtable::entrycount, switch_hashtable::eqfn, entry::h, switch_frame_geometry::h, switch_hashtable::hashfn, switch_hashtable::loadlimit, memset(), prime_table_length, switch_hashtable::primeindex, primes, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_hashtable::table, and switch_hashtable::tablelength.

Referenced by switch_core_hash_init_case(), and switch_core_inthash_init().

59 {
61  unsigned int pindex, size = primes[0];
62 
63  /* Check requested hashtable isn't too large */
64  if (minsize > (1u << 30)) {*hp = NULL; return SWITCH_STATUS_FALSE;}
65  /* Enforce size as prime */
66  for (pindex=0; pindex < prime_table_length; pindex++) {
67  if (primes[pindex] > minsize) {
68  size = primes[pindex];
69  break;
70  }
71  }
72  h = (switch_hashtable_t *) malloc(sizeof(switch_hashtable_t));
73 
74  if (NULL == h) abort(); /*oom*/
75 
76  h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
77 
78  if (NULL == h->table) abort(); /*oom*/
79 
80  memset(h->table, 0, size * sizeof(struct entry *));
81  h->tablelength = size;
82  h->primeindex = pindex;
83  h->entrycount = 0;
84  h->hashfn = hashf;
85  h->eqfn = eqf;
86  h->loadlimit = (unsigned int) ceil(size * max_load_factor);
87 
88  *hp = h;
89  return SWITCH_STATUS_SUCCESS;
90 }
unsigned int h
const unsigned int prime_table_length
const float max_load_factor
int(* eqfn)(void *k1, void *k2)
unsigned int(* hashfn)(void *k)
static const unsigned int primes[]
memset(buf, 0, buflen)

◆ switch_hashtable_count()

unsigned int switch_hashtable_count ( switch_hashtable_t h)

Definition at line 151 of file switch_hashtable.c.

Referenced by switch_jb_destroy().

152 {
153  return h->entrycount;
154 }

◆ switch_hashtable_destroy()

void switch_hashtable_destroy ( switch_hashtable_t **  h)

Definition at line 253 of file switch_hashtable.c.

References entry::destructor, entry::flags, freekey, entry::h, HASHTABLE_FLAG_FREE_KEY, HASHTABLE_FLAG_FREE_VALUE, entry::k, entry::next, switch_safe_free, and entry::v.

Referenced by switch_core_hash_destroy(), and switch_core_inthash_destroy().

254 {
255  unsigned int i;
256  struct entry *e, *f;
257  struct entry **table = (*h)->table;
258 
259  for (i = 0; i < (*h)->tablelength; i++) {
260  e = table[i];
261  while (NULL != e) {
262  f = e; e = e->next;
263 
264  if (f->flags & HASHTABLE_FLAG_FREE_KEY) {
265  freekey(f->k);
266  }
267 
268  if (f->flags & HASHTABLE_FLAG_FREE_VALUE) {
269  switch_safe_free(f->v);
270  } else if (f->destructor) {
271  f->destructor(f->v);
272  f->v = NULL;
273  }
274  switch_safe_free(f);
275  }
276  }
277 
278  switch_safe_free((*h)->table);
279  free(*h);
280  *h = NULL;
281 }
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
hashtable_flag_t flags
#define freekey(X)
hashtable_destructor_t destructor
struct entry * next

◆ switch_hashtable_first_iter()

switch_hashtable_iterator_t* switch_hashtable_first_iter ( switch_hashtable_t h,
switch_hashtable_iterator_t it 
)

Definition at line 316 of file switch_hashtable.c.

References switch_hashtable_iterator::e, entry::h, switch_hashtable_iterator::h, switch_hashtable_iterator::pos, switch_assert, switch_hashtable_next(), and switch_zmalloc.

Referenced by switch_core_hash_first_iter().

317 {
318  switch_hashtable_iterator_t *iterator;
319 
320  if (it) {
321  iterator = it;
322  } else {
323  switch_zmalloc(iterator, sizeof(*iterator));
324  }
325 
326  switch_assert(iterator);
327 
328  iterator->pos = 0;
329  iterator->e = NULL;
330  iterator->h = h;
331 
332  return switch_hashtable_next(&iterator);
333 }
unsigned int h
struct switch_hashtable * h
#define switch_zmalloc(ptr, len)
#define switch_assert(expr)
switch_hashtable_iterator_t * switch_hashtable_next(switch_hashtable_iterator_t **iP)

◆ switch_hashtable_insert_destructor()

int switch_hashtable_insert_destructor ( switch_hashtable_t h,
void *  k,
void *  v,
hashtable_flag_t  flags,
hashtable_destructor_t  destructor 
)

Definition at line 194 of file switch_hashtable.c.

References _switch_hashtable_remove(), entry::destructor, entry::flags, entry::h, hash, HASHTABLE_DUP_CHECK, hashtable_expand(), index, indexFor(), entry::k, entry::next, SWITCH_DECLARE, and entry::v.

Referenced by switch_core_hash_insert_alloc_destructor(), switch_core_hash_insert_auto_free(), switch_core_hash_insert_destructor(), switch_core_hash_insert_dup_auto_free(), switch_core_hash_insert_dup_destructor(), switch_core_hash_insert_pointer(), and switch_core_inthash_insert().

195 {
196  struct entry *e;
197  unsigned int hashvalue = hash(h, k);
198  unsigned index = indexFor(h->tablelength, hashvalue);
199 
200  if (flags & HASHTABLE_DUP_CHECK) {
201  _switch_hashtable_remove(h, k, hashvalue, index);
202  }
203 
204  if (++(h->entrycount) > h->loadlimit)
205  {
206  /* Ignore the return value. If expand fails, we should
207  * still try cramming just this value into the existing table
208  * -- we may not have memory for a larger table, but one more
209  * element may be ok. Next time we insert, we'll try expanding again.*/
210  hashtable_expand(h);
211  index = indexFor(h->tablelength, hashvalue);
212  }
213  e = (struct entry *)malloc(sizeof(struct entry));
214  if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
215  e->h = hashvalue;
216  e->k = k;
217  e->v = v;
218  e->flags = flags;
219  e->destructor = destructor;
220  e->next = h->table[index];
221  h->table[index] = e;
222  return -1;
223 }
unsigned int h
static __inline__ unsigned int indexFor(unsigned int tablelength, unsigned int hashvalue)
switch_hash_t * hash
Definition: switch_event.c:76
int index
Definition: switch_cJSON.h:160
static int hashtable_expand(switch_hashtable_t *h)
hashtable_flag_t flags
static void * _switch_hashtable_remove(switch_hashtable_t *h, void *k, unsigned int hashvalue, unsigned int index)
hashtable_destructor_t destructor
struct entry * next

◆ switch_hashtable_next()

switch_hashtable_iterator_t* switch_hashtable_next ( switch_hashtable_iterator_t **  iP)

Definition at line 283 of file switch_hashtable.c.

References switch_hashtable_iterator::e, switch_hashtable_iterator::h, entry::next, switch_hashtable_iterator::pos, switch_hashtable::table, and switch_hashtable::tablelength.

Referenced by switch_core_hash_next(), and switch_hashtable_first_iter().

284 {
285 
287 
288  if (i->e) {
289  if ((i->e = i->e->next) != 0) {
290  return i;
291  } else {
292  i->pos++;
293  }
294  }
295 
296  while(i->pos < i->h->tablelength && !i->h->table[i->pos]) {
297  i->pos++;
298  }
299 
300  if (i->pos >= i->h->tablelength) {
301  goto end;
302  }
303 
304  if ((i->e = i->h->table[i->pos]) != 0) {
305  return i;
306  }
307 
308  end:
309 
310  free(i);
311  *iP = NULL;
312 
313  return NULL;
314 }
struct switch_hashtable * h
struct entry * next

◆ switch_hashtable_remove()

void* switch_hashtable_remove ( switch_hashtable_t h,
void *  k 
)

Definition at line 244 of file switch_hashtable.c.

References _switch_hashtable_remove(), entry::h, hash, indexFor(), entry::k, and SWITCH_DECLARE.

Referenced by switch_core_hash_delete(), and switch_core_inthash_delete().

245 {
246  unsigned int hashvalue = hash(h,k);
247  return _switch_hashtable_remove(h, k, hashvalue, indexFor(h->tablelength,hashvalue));
248 }
static __inline__ unsigned int indexFor(unsigned int tablelength, unsigned int hashvalue)
switch_hash_t * hash
Definition: switch_event.c:76
static void * _switch_hashtable_remove(switch_hashtable_t *h, void *k, unsigned int hashvalue, unsigned int index)

◆ switch_hashtable_search()

void* switch_hashtable_search ( switch_hashtable_t h,
void *  k 
)

Definition at line 227 of file switch_hashtable.c.

References entry::h, hash, index, indexFor(), entry::k, entry::next, SWITCH_DECLARE, and entry::v.

Referenced by switch_core_hash_find(), and switch_core_inthash_find().

228 {
229  struct entry *e;
230  unsigned int hashvalue, index;
231  hashvalue = hash(h,k);
232  index = indexFor(h->tablelength,hashvalue);
233  e = h->table[index];
234  while (NULL != e) {
235  /* Check hash value to short circuit heavier comparison */
236  if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
237  e = e->next;
238  }
239  return NULL;
240 }
unsigned int h
static __inline__ unsigned int indexFor(unsigned int tablelength, unsigned int hashvalue)
switch_hash_t * hash
Definition: switch_event.c:76
int index
Definition: switch_cJSON.h:160
int(* eqfn)(void *k1, void *k2)
struct entry * next

◆ switch_hashtable_this()

void switch_hashtable_this ( switch_hashtable_iterator_t i,
const void **  key,
switch_ssize_t klen,
void **  val 
)

Definition at line 342 of file switch_hashtable.c.

References switch_hashtable_iterator::e, entry::k, and entry::v.

Referenced by switch_core_hash_this().

343 {
344  if (i->e) {
345  if (key) {
346  *key = i->e->k;
347  }
348  if (klen) {
349  *klen = (int)strlen(i->e->k);
350  }
351  if (val) {
352  *val = i->e->v;
353  }
354  } else {
355  if (key) {
356  *key = NULL;
357  }
358  if (klen) {
359  *klen = 0;
360  }
361  if (val) {
362  *val = NULL;
363  }
364  }
365 }
char * key
Definition: switch_msrp.c:64

◆ switch_hashtable_this_val()

void switch_hashtable_this_val ( switch_hashtable_iterator_t i,
void *  val 
)

Definition at line 335 of file switch_hashtable.c.

References switch_hashtable_iterator::e, and entry::v.

Referenced by switch_core_hash_this_val().

336 {
337  if (i->e) {
338  i->e->v = val;
339  }
340 }

Variable Documentation

◆ max_load_factor

const float max_load_factor = 0.65f

Definition at line 52 of file switch_hashtable.c.

◆ prime_table_length

const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0])

Definition at line 51 of file switch_hashtable.c.

Referenced by hashtable_expand(), and switch_create_hashtable().

◆ primes

const unsigned int primes[]
static
Initial value:
= {
53, 97, 193, 389,
769, 1543, 3079, 6151,
12289, 24593, 49157, 98317,
196613, 393241, 786433, 1572869,
3145739, 6291469, 12582917, 25165843,
50331653, 100663319, 201326611, 402653189,
805306457, 1610612741
}

Definition at line 42 of file switch_hashtable.c.

Referenced by hashtable_expand(), and switch_create_hashtable().