clean-up: remove cockoo hash (unused and unmaintained)
Cockoo hashing is a thrilling algorithm. We investigated it during the time or our first draft towards a confirugation system in 2008. This usage turned up some problems -- not sure if based on the implementation or the algorithm itself; at that time, we just switched to the probabilistic splay tree. The whole configuration system effort stalled afterwards; so the cuckoo implementation remained in tree as a zombie.
This commit is contained in:
parent
07822182d9
commit
97fec4179b
4 changed files with 2 additions and 737 deletions
|
|
@ -142,7 +142,7 @@ lumiera_config_lookup_item_tail_find (LumieraConfigLookup self, const char* key)
|
|||
|
||||
|
||||
|
||||
/* Lookup hash entries for the cuckoo hash */
|
||||
/* == lookup hash entries using the PSplay tree */
|
||||
|
||||
|
||||
/** @internal Structure defining single hash table entries.*/
|
||||
|
|
|
|||
528
src/lib/cuckoo.c
528
src/lib/cuckoo.c
|
|
@ -1,528 +0,0 @@
|
|||
/*
|
||||
A cuckoo hash implementation
|
||||
|
||||
Copyright (C)
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "cuckoo.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define CUCKOO_GRANULARITY int
|
||||
|
||||
enum compact_state
|
||||
{
|
||||
COMPACTING_OFF,
|
||||
COMPACTING_AUTO,
|
||||
COMPACTED
|
||||
};
|
||||
|
||||
struct cuckoo_struct
|
||||
{
|
||||
size_t size; /* t1 = 4*size; t2 = 2*size; t3 = size */
|
||||
size_t itemsize;
|
||||
|
||||
struct cuckoo_vtable vtable;
|
||||
|
||||
uint32_t r1; /* random, reset for each rehash */
|
||||
uint32_t r2;
|
||||
uint32_t r3;
|
||||
|
||||
void* t1;
|
||||
void* t2;
|
||||
void* t3;
|
||||
|
||||
unsigned maxloops; /* sqrt (4 * size) */
|
||||
|
||||
enum compact_state autocompact;
|
||||
size_t elements;
|
||||
};
|
||||
|
||||
|
||||
static inline uint32_t cuckoo_fast_prng ()
|
||||
{
|
||||
static uint32_t rnd = 0xbabeface;
|
||||
return rnd = rnd<<1 ^ ((rnd>>30) & 1) ^ ((rnd>>2) & 1);
|
||||
}
|
||||
|
||||
static inline int
|
||||
iszero (void* mem, size_t size)
|
||||
{
|
||||
while (size && !*(CUCKOO_GRANULARITY*)mem)
|
||||
{
|
||||
size -= sizeof (CUCKOO_GRANULARITY);
|
||||
mem += sizeof (CUCKOO_GRANULARITY);
|
||||
}
|
||||
return !size;
|
||||
}
|
||||
|
||||
static inline void
|
||||
xmemmov (void* dst, void* src, size_t size)
|
||||
{
|
||||
while (size)
|
||||
{
|
||||
size -= sizeof (CUCKOO_GRANULARITY);
|
||||
*(CUCKOO_GRANULARITY*)(dst + size) = *(CUCKOO_GRANULARITY*)(src + size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Cuckoo
|
||||
cuckoo_init (Cuckoo self, size_t itemsize, struct cuckoo_vtable* vtable)
|
||||
{
|
||||
if (!self)
|
||||
return NULL;
|
||||
|
||||
self->size = 16;
|
||||
self->itemsize = (itemsize * sizeof (CUCKOO_GRANULARITY)
|
||||
+ sizeof (CUCKOO_GRANULARITY) - 1) / sizeof (CUCKOO_GRANULARITY); /* round up to next CUCKOO_GRANULARITY boundary */
|
||||
self->r1 = cuckoo_fast_prng ();
|
||||
self->r2 = cuckoo_fast_prng ();
|
||||
self->r3 = cuckoo_fast_prng ();
|
||||
|
||||
if (!vtable->h1 || !vtable->h2 || !vtable->h3)
|
||||
return NULL;
|
||||
|
||||
self->vtable.h1 = vtable->h1;
|
||||
self->vtable.h2 = vtable->h2;
|
||||
self->vtable.h3 = vtable->h3;
|
||||
|
||||
if (!vtable->cmp)
|
||||
return NULL;
|
||||
|
||||
self->vtable.cmp = vtable->cmp;
|
||||
|
||||
self->vtable.dtor = vtable->dtor;
|
||||
|
||||
if (vtable->mov)
|
||||
self->vtable.mov = vtable->mov;
|
||||
else
|
||||
self->vtable.mov = xmemmov;
|
||||
|
||||
self->t1 = calloc (self->size * 4, itemsize);
|
||||
self->t2 = calloc (self->size * 2, itemsize);
|
||||
self->t3 = calloc (self->size, itemsize);
|
||||
if (!self->t1 || !self->t2 || !self->t3)
|
||||
{
|
||||
free (self->t1);
|
||||
free (self->t2);
|
||||
free (self->t3);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->maxloops = 1;
|
||||
while (self->maxloops * self->maxloops < self->size * 4)
|
||||
++self->maxloops;
|
||||
|
||||
self->autocompact = COMPACTING_AUTO;
|
||||
self->elements = 0;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
Cuckoo
|
||||
cuckoo_new (size_t itemsize, struct cuckoo_vtable* vtable)
|
||||
{
|
||||
Cuckoo self = malloc (sizeof (struct cuckoo_struct));
|
||||
if (!cuckoo_init (self, itemsize, vtable))
|
||||
{
|
||||
free (self);
|
||||
return NULL;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
Cuckoo
|
||||
cuckoo_destroy (Cuckoo self)
|
||||
{
|
||||
if (self)
|
||||
{
|
||||
|
||||
if (self->vtable.dtor)
|
||||
{
|
||||
void* elem;
|
||||
for (elem = self->t1; elem < self->t1 + self->size * 4; elem += self->size)
|
||||
self->vtable.dtor (elem);
|
||||
for (elem = self->t2; elem < self->t1 + self->size * 2; elem += self->size)
|
||||
self->vtable.dtor (elem);
|
||||
for (elem = self->t3; elem < self->t1 + self->size; elem += self->size)
|
||||
self->vtable.dtor (elem);
|
||||
}
|
||||
|
||||
free (self->t1);
|
||||
free (self->t2);
|
||||
free (self->t3);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cuckoo_delete (Cuckoo self)
|
||||
{
|
||||
free (cuckoo_destroy (self));
|
||||
}
|
||||
|
||||
|
||||
static void*
|
||||
cuckoo_insert_internal_ (Cuckoo self, void* item)
|
||||
{
|
||||
void* pos;
|
||||
CUCKOO_GRANULARITY tmp[self->itemsize / sizeof(CUCKOO_GRANULARITY)];
|
||||
|
||||
for (unsigned n = 0; n < self->maxloops; ++n)
|
||||
{
|
||||
/* find nest */
|
||||
pos = self->t1 + self->itemsize * (self->vtable.h1 (item, self->r1) % (4*self->size));
|
||||
/* kick old egg out */
|
||||
if (iszero (pos, self->itemsize))
|
||||
memset (tmp, 0, self->itemsize);
|
||||
else
|
||||
self->vtable.mov (tmp, pos, self->itemsize);
|
||||
/* lay egg */
|
||||
self->vtable.mov (pos, item, self->itemsize);
|
||||
|
||||
if (iszero (tmp, self->itemsize))
|
||||
return pos;
|
||||
|
||||
/* find nest */
|
||||
pos = self->t2 + self->itemsize * (self->vtable.h2 (tmp, self->r2) % (2*self->size));
|
||||
/* kick old egg out */
|
||||
self->vtable.mov (item, pos, self->itemsize);
|
||||
/* lay egg */
|
||||
self->vtable.mov (pos, tmp, self->itemsize);
|
||||
|
||||
if (iszero (item, self->itemsize))
|
||||
return pos;
|
||||
|
||||
/* find nest */
|
||||
pos = self->t3 + self->itemsize * (self->vtable.h3 (item, self->r3) % self->size);
|
||||
/* kick old egg out */
|
||||
self->vtable.mov (tmp, pos, self->itemsize);
|
||||
/* lay egg */
|
||||
self->vtable.mov (pos, item, self->itemsize);
|
||||
|
||||
if (iszero (tmp, self->itemsize))
|
||||
return pos;
|
||||
|
||||
/* copy tmp to item, which will be reinserted on next interation / after rehashing */
|
||||
self->vtable.mov (item, tmp, self->itemsize);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
cuckoo_nelements (Cuckoo self)
|
||||
{
|
||||
return self->elements;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cuckoo_rehash (Cuckoo self)
|
||||
{
|
||||
retry1:
|
||||
|
||||
self->r1 = cuckoo_fast_prng ();
|
||||
|
||||
for (size_t i = 0; i < 4*self->size; ++i)
|
||||
{
|
||||
unsigned n;
|
||||
void* pos = self->t1 + self->itemsize * i;
|
||||
if (!iszero (pos, self->itemsize))
|
||||
{
|
||||
for (n = 0; n < self->maxloops; ++n)
|
||||
{
|
||||
unsigned hash = self->vtable.h1 (pos, self->r1) % (4*self->size);
|
||||
if (hash != i)
|
||||
{
|
||||
char t[self->itemsize];
|
||||
void* hpos = self->t1 + self->itemsize * hash;
|
||||
self->vtable.mov (t, hpos, self->itemsize);
|
||||
self->vtable.mov (hpos, pos, self->itemsize);
|
||||
self->vtable.mov (pos, t, self->itemsize);
|
||||
if (iszero (t, self->itemsize))
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (n == self->maxloops)
|
||||
goto retry1;
|
||||
}
|
||||
}
|
||||
|
||||
retry2:
|
||||
self->r2 = cuckoo_fast_prng ();
|
||||
|
||||
for (size_t i = 0; i < 2*self->size; ++i)
|
||||
{
|
||||
unsigned n;
|
||||
void* pos = self->t2 + self->itemsize * i;
|
||||
if (!iszero (pos, self->itemsize))
|
||||
{
|
||||
for (n = 0; n < self->maxloops; ++n)
|
||||
{
|
||||
unsigned hash = self->vtable.h2 (pos, self->r2) % (2*self->size);
|
||||
if (hash != i)
|
||||
{
|
||||
char t[self->itemsize];
|
||||
void* hpos = self->t2 + self->itemsize * hash;
|
||||
self->vtable.mov (t, hpos, self->itemsize);
|
||||
self->vtable.mov (hpos, pos, self->itemsize);
|
||||
self->vtable.mov (pos, t, self->itemsize);
|
||||
if (iszero (t, self->itemsize))
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (n == self->maxloops)
|
||||
goto retry2;
|
||||
}
|
||||
}
|
||||
|
||||
retry3:
|
||||
self->r3 = cuckoo_fast_prng ();
|
||||
|
||||
for (size_t i = 0; i < self->size; ++i)
|
||||
{
|
||||
unsigned n;
|
||||
void* pos = self->t3 + self->itemsize * i;
|
||||
if (!iszero (pos, self->itemsize))
|
||||
{
|
||||
for (n = 0; n < self->maxloops; ++n)
|
||||
{
|
||||
unsigned hash = self->vtable.h3 (pos, self->r3) % self->size;
|
||||
if (hash != i)
|
||||
{
|
||||
char t[self->itemsize];
|
||||
void* hpos = self->t3 + self->itemsize * hash;
|
||||
self->vtable.mov (t, hpos, self->itemsize);
|
||||
self->vtable.mov (hpos, pos, self->itemsize);
|
||||
self->vtable.mov (pos, t, self->itemsize);
|
||||
if (iszero (t, self->itemsize))
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (n == self->maxloops)
|
||||
goto retry3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
cuckoo_grow (Cuckoo self)
|
||||
{
|
||||
/* rotate hashfuncs, tables, randoms */
|
||||
cuckoo_hashfunc th = self->vtable.h3;
|
||||
self->vtable.h3 = self->vtable.h2;
|
||||
self->vtable.h2 = self->vtable.h1;
|
||||
self->vtable.h1 = th;
|
||||
|
||||
uint32_t tr = self->r3;
|
||||
self->r3 = self->r2;
|
||||
self->r2 = self->r1;
|
||||
self->r1 = tr;
|
||||
|
||||
void* tt = self->t3;
|
||||
self->t3 = self->t2;
|
||||
self->t2 = self->t1;
|
||||
|
||||
/* double new base size */
|
||||
self->size *= 2;
|
||||
while (self->maxloops * self->maxloops < self->size * 4)
|
||||
++self->maxloops;
|
||||
|
||||
/* alloc new t1 */
|
||||
self->t1 = calloc (self->size * 4, self->itemsize);
|
||||
if (!self->t1)
|
||||
{
|
||||
self->t1 = tt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* reinsert tt */
|
||||
size_t ttsize = self->size / 2;
|
||||
for (size_t i = 0; i < ttsize; ++i)
|
||||
{
|
||||
void* pos = tt + i * self->itemsize;
|
||||
if (!iszero (pos, self->itemsize))
|
||||
{
|
||||
while (!cuckoo_insert_internal_ (self, pos))
|
||||
cuckoo_rehash (self);
|
||||
}
|
||||
}
|
||||
free (tt);
|
||||
|
||||
self->autocompact = COMPACTING_AUTO;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cuckoo_reserve (Cuckoo self, size_t more)
|
||||
{
|
||||
int ret = 1;
|
||||
if (more)
|
||||
while (self->elements+self->maxloops+more >= 6*self->size)
|
||||
ret = cuckoo_grow (self);
|
||||
|
||||
self->autocompact = COMPACTING_OFF;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cuckoo_compact (Cuckoo self)
|
||||
{
|
||||
if (self->autocompact == COMPACTED)
|
||||
return 1;
|
||||
|
||||
if (self->size > 2 && self->elements < self->size * 3)
|
||||
{
|
||||
cuckoo_hashfunc th = self->vtable.h1;
|
||||
self->vtable.h1 = self->vtable.h2;
|
||||
self->vtable.h2 = self->vtable.h3;
|
||||
self->vtable.h3 = th;
|
||||
|
||||
uint32_t tr = self->r1;
|
||||
self->r1 = self->r2;
|
||||
self->r2 = self->r3;
|
||||
self->r3 = tr;
|
||||
|
||||
void* tt = self->t1;
|
||||
self->t1 = self->t2;
|
||||
self->t2 = self->t3;
|
||||
|
||||
/* halve base size */
|
||||
self->size /= 2;
|
||||
while (self->maxloops * self->maxloops >= self->size * 4)
|
||||
--self->maxloops;
|
||||
|
||||
/* alloc new t3 */
|
||||
self->t3 = calloc (self->size, self->itemsize);
|
||||
if (!self->t3)
|
||||
{
|
||||
self->t3 = tt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* reinsert tt */
|
||||
size_t ttsize = self->size * 8;
|
||||
for (size_t i = 0; i < ttsize; ++i)
|
||||
{
|
||||
void* pos = tt + i * self->itemsize;
|
||||
if (!iszero (pos, self->itemsize))
|
||||
{
|
||||
--self->elements;
|
||||
cuckoo_insert (self, pos);
|
||||
}
|
||||
}
|
||||
free (tt);
|
||||
self->autocompact = COMPACTED;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
cuckoo_insert (Cuckoo self, void* item)
|
||||
{
|
||||
char tmp[self->itemsize];
|
||||
|
||||
void* found;
|
||||
if ((found = cuckoo_find (self, item)))
|
||||
{
|
||||
if (self->vtable.dtor)
|
||||
self->vtable.dtor (found);
|
||||
self->vtable.mov (found, item, self->itemsize);
|
||||
return found;
|
||||
}
|
||||
|
||||
self->vtable.mov (tmp, item, self->itemsize);
|
||||
|
||||
for (unsigned n = 6; n; --n) /* rehash/grow loop */
|
||||
{
|
||||
if ((found = cuckoo_insert_internal_ (self, tmp)))
|
||||
{
|
||||
++self->elements;
|
||||
return found;
|
||||
}
|
||||
|
||||
if (self->elements > n*self->size)
|
||||
{
|
||||
n = 6;
|
||||
if (!cuckoo_grow (self))
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
cuckoo_rehash (self);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
cuckoo_find (Cuckoo self, void* item)
|
||||
{
|
||||
void* pos;
|
||||
|
||||
pos = self->t1 + self->itemsize * (self->vtable.h1 (item, self->r1) % (4*self->size));
|
||||
if (!iszero (pos, self->itemsize) && self->vtable.cmp (item, pos))
|
||||
return pos;
|
||||
|
||||
pos = self->t2 + self->itemsize * (self->vtable.h2 (item, self->r2) % (2*self->size));
|
||||
if (!iszero (pos, self->itemsize) && self->vtable.cmp (item, pos))
|
||||
return pos;
|
||||
|
||||
pos = self->t3 + self->itemsize * (self->vtable.h3 (item, self->r3) % self->size);
|
||||
if (!iszero (pos, self->itemsize) && self->vtable.cmp (item, pos))
|
||||
return pos;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cuckoo_remove (Cuckoo self, void* item)
|
||||
{
|
||||
if (item)
|
||||
{
|
||||
if (self->vtable.dtor)
|
||||
self->vtable.dtor (item);
|
||||
|
||||
memset (item, 0, self->itemsize);
|
||||
--self->elements;
|
||||
|
||||
if (self->autocompact == COMPACTING_AUTO && self->size > 2 && self->elements <= self->size*2)
|
||||
cuckoo_compact (self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
197
src/lib/cuckoo.h
197
src/lib/cuckoo.h
|
|
@ -1,197 +0,0 @@
|
|||
/*
|
||||
A cuckoo hash implementation
|
||||
|
||||
Copyright (C)
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef CUCKOO_H
|
||||
#define CUCKOO_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Cuckoo hashing
|
||||
* This hashing gives guaranteed O(1) lookup complexity and amortized O(1) insert and remove complexity.
|
||||
* Hash tables by default grow and shrink automatically. It is posible to preallocate entries and turn
|
||||
* automatic shrinking off taking out the memory management factors for insert and remove operations.
|
||||
* This implementation uses 3 Tables which exponential growing sizes.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct cuckoo_struct;
|
||||
typedef struct cuckoo_struct * Cuckoo;
|
||||
|
||||
/**
|
||||
* Hash function.
|
||||
* User supplied universal hash function
|
||||
* @param item address of the item to be hashed
|
||||
* @param r pseudo random number, 31 significant bits, regenerated on each rehash
|
||||
* @return hash value
|
||||
*/
|
||||
typedef size_t (*cuckoo_hashfunc)(const void* item, const uint32_t r);
|
||||
|
||||
/**
|
||||
* Compare function.
|
||||
* User supplied compare function
|
||||
* @param item1 address of the first item
|
||||
* @param item2 address of the second item
|
||||
* @return 1 when the items are identical, 0 otherwise
|
||||
*/
|
||||
typedef int (*cuckoo_cmpfunc)(const void* item1, const void* item2);
|
||||
|
||||
/**
|
||||
* Item destructor function.
|
||||
* User supplied destructor function. This function is called when items are removed
|
||||
* from the hash or at hash detroy/delete time. Must be safe to be called on a zeroed element.
|
||||
* @param item address of the item to be destroyed
|
||||
*/
|
||||
typedef void (*cuckoo_dtorfunc)(void* item);
|
||||
|
||||
/**
|
||||
* Move function.
|
||||
* User supplied item move function
|
||||
* @param dest target address for the move operation
|
||||
* @param src source for the move operation
|
||||
* @param size size of a item (requested size rounded up to the next CUCKOO_GRANULARITY)
|
||||
* It might be necessary to invalidate the source in some case, cuckoo will zero it out
|
||||
* after moving.
|
||||
*/
|
||||
typedef void (*cuckoo_movfunc)(void* dest, void* src, size_t size);
|
||||
|
||||
|
||||
/**
|
||||
* Function table used to specialise various functions used by the hash.
|
||||
* TODO some elements might be NULL, then defaults are used
|
||||
*/
|
||||
struct cuckoo_vtable
|
||||
{
|
||||
cuckoo_hashfunc h1;
|
||||
cuckoo_hashfunc h2;
|
||||
cuckoo_hashfunc h3;
|
||||
cuckoo_cmpfunc cmp;
|
||||
cuckoo_dtorfunc dtor;
|
||||
cuckoo_movfunc mov;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initialise a cuckoo hash.
|
||||
* @param self pointer to a uninitialised cuckoo datastructure
|
||||
* @param itemsize size for a single hash entry, will be rounded up to align CUCKOO_GRANULARITY
|
||||
* @param vtable initialised vtable
|
||||
* @return The initialised hashtable or NULL at allocation failure
|
||||
*/
|
||||
Cuckoo
|
||||
cuckoo_init (Cuckoo self, size_t itemsize, struct cuckoo_vtable* vtable);
|
||||
|
||||
/**
|
||||
* Allocate a new cuckoo hash.
|
||||
* @param itemsize size for a single hash entry, will be rounded up to align CUCKOO_GRANULARITY
|
||||
* @param startsize initial size of table t3, as 2's exponent
|
||||
* @param vtable initialised vtable
|
||||
* @return The initialised hashtable or NULL at allocation failure
|
||||
*/
|
||||
Cuckoo
|
||||
cuckoo_new (size_t itemsize, struct cuckoo_vtable* vtable);
|
||||
|
||||
|
||||
/**
|
||||
* Destroy a cuckoo hash.
|
||||
* Frees internal used resources.
|
||||
* @param self cuckoo hash to destroy
|
||||
* @return The now uninitialised hashtable
|
||||
*/
|
||||
Cuckoo
|
||||
cuckoo_destroy (Cuckoo self);
|
||||
|
||||
/**
|
||||
* Deallocate a cuckoo hash.
|
||||
* @param self handle of the hash table to be freed
|
||||
*/
|
||||
void
|
||||
cuckoo_delete (Cuckoo self);
|
||||
|
||||
/**
|
||||
* Get the number of elements stored in a hash.
|
||||
* @return number of elements, 0 when empty
|
||||
*/
|
||||
size_t
|
||||
cuckoo_nelements (Cuckoo self);
|
||||
|
||||
/**
|
||||
* Insert an element into a hash.
|
||||
* amortized O(1) complexity because it may rarely rehash the tables or even grow them.
|
||||
* see cuckoo_reserve() about how to preallocate entries to prevent the growing costs.
|
||||
* Inserting an element already in the hash calls the dtor for the old entry and places
|
||||
* the new one into the hash.
|
||||
* @param self handle to the hash table
|
||||
* @param item pointer to a item to be inserted
|
||||
* @return pointer to inserted element on successful insert, NULL on allocation failure
|
||||
* Note: at failure there is one arbitary hash cell lost!
|
||||
*/
|
||||
void*
|
||||
cuckoo_insert (Cuckoo self, void* item);
|
||||
|
||||
/**
|
||||
* Find a value by key in a hash.
|
||||
* @param self handle to the hash table
|
||||
* @param item pointer to an item to be looked up
|
||||
* @return found object or NULL if not present
|
||||
*/
|
||||
void*
|
||||
cuckoo_find (Cuckoo self, void* item);
|
||||
|
||||
/**
|
||||
* Remove a item from a hash.
|
||||
* amortized O(1) complexity when it automatically shrink its tables.
|
||||
* guaranteed O(1) complexity when automatic shrinking is turned off.
|
||||
* see cuckoo_reserve() about how turn automatic shrinking off.
|
||||
* @param self handle to the hash table
|
||||
* @param item pointer to the item to be removed
|
||||
*/
|
||||
void
|
||||
cuckoo_remove (Cuckoo self, void* item);
|
||||
|
||||
/**
|
||||
* Shrink the hash sizes when possible and turn autocompacting on.
|
||||
* only useful when autmatic shrinking is turned off.
|
||||
* see cuckoo_reserve() about how turn shrinking off.
|
||||
* @param self handle to the hash table
|
||||
*/
|
||||
int
|
||||
cuckoo_compact (Cuckoo self);
|
||||
|
||||
/**
|
||||
* Prereserve hash entries and turn autocompacting off.
|
||||
* @param self handle to the hash table
|
||||
* @param more number of entries to be additionally reserved
|
||||
* In rare circumstances inserting into a hash which has reserved some entries
|
||||
* it may still need to rehash (or even rarer) to grow the table.
|
||||
* While autocompacting is turned off, removing is completely O(1).
|
||||
*/
|
||||
int
|
||||
cuckoo_reserve (Cuckoo self, size_t more);
|
||||
|
||||
#endif
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
|
|
@ -402,9 +402,7 @@ TESTS_END
|
|||
|
||||
|
||||
|
||||
/*
|
||||
cuckoo support functions
|
||||
*/
|
||||
/* === PSplay support functions === */
|
||||
|
||||
static int
|
||||
cmp_fn (const void* a, const void* b)
|
||||
|
|
@ -431,10 +429,6 @@ delete_fn (PSplaynode node)
|
|||
}
|
||||
|
||||
|
||||
//static psplay_delete_fn
|
||||
//action_fn (PSplaynode node, const enum psplay_order_e which, int level, void* data)
|
||||
//{
|
||||
//}
|
||||
|
||||
|
||||
static int
|
||||
|
|
@ -455,10 +449,6 @@ fdelete_fn (PSplaynode node)
|
|||
testitem_delete ((TestItem) node);
|
||||
}
|
||||
|
||||
//static psplay_delete_fn
|
||||
//action_fn (PSplaynode node, const enum psplay_order_e which, int level, void* data)
|
||||
//{
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue