summaryrefslogtreecommitdiff
path: root/libhurd-ihash
diff options
context:
space:
mode:
authorneal <neal>2008-02-08 10:01:41 +0000
committerneal <neal>2008-02-08 10:01:41 +0000
commitf0271bdf0b422685f1ac0fbc378192b407e75efa (patch)
treeb2ac8b52346e5b49528954d5a8191af8f18eac4b /libhurd-ihash
parent5669f84c020ae2c4f1c2b648aca643c114f69012 (diff)
libhurd-ihash/
2008-02-08 Neal H. Walfield <neal@gnu.org> * ihash.h: Include <bits/wordsize.h>. (hurd_ihash_key64_t): New definition. (struct _hurd_ihash_item64): New structure. (struct hurd_ihash): Change items's type void *. [__WORDSIZE == 32]: Add field large. (_HURD_IHASH_LARGE): New macro. (HURD_IHASH_INITIALIZER): Take additional argument large. Use it. (hurd_ihash_init): Take additional argument large. (hurd_ihash_buffer_size): Likewise. (hurd_ihash_init_with_buffer): Likewise. (hurd_ihash_create): Likewise. (hurd_ihash_replace): Change key's type to hurd_ihash_key64_t. (hurd_ihash_add): Likewise. (hurd_ihash_find): Likewise. (hurd_ihash_remove): Likewise. (HURD_IHASH_ITERATE): Rewrite to properly handle both 32- and 64-bit keys. * ihash.c (ITEM): New macro. (VALUE): Likewise. (KEY): Likewise. (ITEM_SIZE): Likewise. (index_empty): Use the above macros rather than accessing HT->ITEMS directly. (index_valid): Likewise and change key's type to a hurd_ihash_key64_t. (find_index): Likewise. (replace_one): Likewise. (hurd_ihash_replace): Likewise. (hurd_ihash_find): Likewise. (hurd_ihash_remove): Likewise. (hurd_ihash_init_internal): Take additional argument large. Use it. (hurd_ihash_init): Likewise. (hurd_ihash_init_with_buffer): Likewise. (hurd_ihash_create): Likewise. (hurd_ihash_buffer_size): Likewise. * t-ihash.c: Include <assert.h>. (main): Expect that TEST_LARGE is defined. Use it when calling hurd_ihash_init. If true, add some tests with 64-bit keys. * Makefile.am (TESTS): Add t-ihash64. (check_PROGRAMS): Likewise. (t_ihash_CPPFLAGS): Add -DTEST_LARGE=false. (t_ihash64_SOURCES): New variable. (t_ihash64_CPPFLAGS): Likewise. viengoos/ 2008-02-08 Neal H. Walfield <neal@gnu.org> * thread.c (thread_init): Update use of hurd_ihash_init_with_buffer to be consistent with new API. * object.c (object_init): Likewise. libpthread/ 2008-02-08 Neal H. Walfield <neal@gnu.org> * sysdeps/hurd/pt-setspecific.c (pthread_setspecific): Update use of hurd_ihash_create to be consistent with API changes.
Diffstat (limited to 'libhurd-ihash')
-rw-r--r--libhurd-ihash/ChangeLog47
-rw-r--r--libhurd-ihash/Makefile.am9
-rw-r--r--libhurd-ihash/ihash.c130
-rw-r--r--libhurd-ihash/ihash.h121
-rw-r--r--libhurd-ihash/t-ihash.c30
5 files changed, 251 insertions, 86 deletions
diff --git a/libhurd-ihash/ChangeLog b/libhurd-ihash/ChangeLog
index ec148f1..33ce1b8 100644
--- a/libhurd-ihash/ChangeLog
+++ b/libhurd-ihash/ChangeLog
@@ -1,3 +1,50 @@
+2008-02-08 Neal H. Walfield <neal@gnu.org>
+
+ * ihash.h: Include <bits/wordsize.h>.
+ (hurd_ihash_key64_t): New definition.
+ (struct _hurd_ihash_item64): New structure.
+ (struct hurd_ihash): Change items's type void *.
+ [__WORDSIZE == 32]: Add field large.
+ (_HURD_IHASH_LARGE): New macro.
+ (HURD_IHASH_INITIALIZER): Take additional argument large. Use it.
+ (hurd_ihash_init): Take additional argument large.
+ (hurd_ihash_buffer_size): Likewise.
+ (hurd_ihash_init_with_buffer): Likewise.
+ (hurd_ihash_create): Likewise.
+ (hurd_ihash_replace): Change key's type to hurd_ihash_key64_t.
+ (hurd_ihash_add): Likewise.
+ (hurd_ihash_find): Likewise.
+ (hurd_ihash_remove): Likewise.
+ (HURD_IHASH_ITERATE): Rewrite to properly handle both 32- and
+ 64-bit keys.
+ * ihash.c (ITEM): New macro.
+ (VALUE): Likewise.
+ (KEY): Likewise.
+ (ITEM_SIZE): Likewise.
+ (index_empty): Use the above macros rather than accessing
+ HT->ITEMS directly.
+ (index_valid): Likewise and change key's type to a
+ hurd_ihash_key64_t.
+ (find_index): Likewise.
+ (replace_one): Likewise.
+ (hurd_ihash_replace): Likewise.
+ (hurd_ihash_find): Likewise.
+ (hurd_ihash_remove): Likewise.
+ (hurd_ihash_init_internal): Take additional argument large. Use
+ it.
+ (hurd_ihash_init): Likewise.
+ (hurd_ihash_init_with_buffer): Likewise.
+ (hurd_ihash_create): Likewise.
+ (hurd_ihash_buffer_size): Likewise.
+ * t-ihash.c: Include <assert.h>.
+ (main): Expect that TEST_LARGE is defined. Use it when calling
+ hurd_ihash_init. If true, add some tests with 64-bit keys.
+ * Makefile.am (TESTS): Add t-ihash64.
+ (check_PROGRAMS): Likewise.
+ (t_ihash_CPPFLAGS): Add -DTEST_LARGE=false.
+ (t_ihash64_SOURCES): New variable.
+ (t_ihash64_CPPFLAGS): Likewise.
+
2008-01-24 Neal H. Walfield <neal@gnu.org>
* Makefile.am (t_ihash_SOURCES): Add ihash.c.
diff --git a/libhurd-ihash/Makefile.am b/libhurd-ihash/Makefile.am
index d7a3913..72a0e56 100644
--- a/libhurd-ihash/Makefile.am
+++ b/libhurd-ihash/Makefile.am
@@ -35,8 +35,11 @@ libhurd_ihash_a_SOURCES = ihash.h ihash.c
libhurd_ihash_nomalloc_a_CPPFLAGS = $(AM_CPPFLAGS) -DNO_MALLOC
libhurd_ihash_nomalloc_a_SOURCES = ihash.h ihash.c
-TESTS = t-ihash
+TESTS = t-ihash t-ihash64
+check_PROGRAMS = t-ihash t-ihash64
-check_PROGRAMS = t-ihash
t_ihash_SOURCES = t-ihash.c ihash.h ihash.c
-t_ihash_CPPFLAGS = -DS_PRINTF=printf $(AM_CPPFLAGS)
+t_ihash_CPPFLAGS = -DTEST_LARGE=false -DS_PRINTF=printf $(AM_CPPFLAGS)
+
+t_ihash64_SOURCES = t-ihash.c ihash.h ihash.c
+t_ihash64_CPPFLAGS = -DTEST_LARGE=true -DS_PRINTF=printf $(AM_CPPFLAGS)
diff --git a/libhurd-ihash/ihash.c b/libhurd-ihash/ihash.c
index b16632b..4ba9aaf 100644
--- a/libhurd-ihash/ihash.c
+++ b/libhurd-ihash/ihash.c
@@ -82,22 +82,42 @@ static const unsigned int ihash_nsizes = (sizeof ihash_sizes
/ sizeof ihash_sizes[0]);
+#define ITEM(ht, idx) \
+ (_HURD_IHASH_LARGE (ht) \
+ ? (void *) &((_hurd_ihash_item64_t) (ht)->items)[idx] \
+ : (void *) &((_hurd_ihash_item_t) (ht)->items)[idx])
+
+#define VALUE(ht, idx) \
+ (_HURD_IHASH_LARGE (ht) \
+ ? ((_hurd_ihash_item64_t) ITEM (ht, idx))->value \
+ : ((_hurd_ihash_item_t) ITEM (ht, idx))->value)
+
+#define KEY(ht, idx) \
+ (_HURD_IHASH_LARGE (ht) \
+ ? ((_hurd_ihash_item64_t) ITEM (ht, idx))->key \
+ : ((_hurd_ihash_item_t) ITEM (ht, idx))->key)
+
+#define ITEM_SIZE(large) \
+ ((large) \
+ ? sizeof (struct _hurd_ihash_item64) \
+ : sizeof (struct _hurd_ihash_item))
+
/* Return 1 if the slot with the index IDX in the hash table HT is
empty, and 0 otherwise. */
static inline int
index_empty (hurd_ihash_t ht, unsigned int idx)
{
- return ht->items[idx].value == _HURD_IHASH_EMPTY
- || ht->items[idx].value == _HURD_IHASH_DELETED;
+ return VALUE (ht, idx) == _HURD_IHASH_EMPTY
+ || VALUE (ht, idx) == _HURD_IHASH_DELETED;
}
/* Return 1 if the index IDX in the hash table HT is occupied by the
element with the key KEY. */
static inline int
-index_valid (hurd_ihash_t ht, unsigned int idx, hurd_ihash_key_t key)
+index_valid (hurd_ihash_t ht, unsigned int idx, hurd_ihash_key64_t key)
{
- return !index_empty (ht, idx) && ht->items[idx].key == key;
+ return !index_empty (ht, idx) && KEY (ht, idx) == key;
}
@@ -105,7 +125,7 @@ index_valid (hurd_ihash_t ht, unsigned int idx, hurd_ihash_key_t key)
of that key. You must subsequently check with index_valid() if the
returned index is valid. */
static inline int
-find_index (hurd_ihash_t ht, hurd_ihash_key_t key)
+find_index (hurd_ihash_t ht, hurd_ihash_key64_t key)
{
unsigned int idx;
unsigned int i;
@@ -114,7 +134,7 @@ find_index (hurd_ihash_t ht, hurd_ihash_key_t key)
idx = key % ht->size;
- if (ht->items[idx].value == _HURD_IHASH_EMPTY || ht->items[idx].key == key)
+ if (VALUE (ht, idx) == _HURD_IHASH_EMPTY || KEY (ht, idx) == key)
return idx;
/* Instead of calculating idx + 1, idx + 4, idx + 9, ..., idx + i^2,
@@ -127,15 +147,15 @@ find_index (hurd_ihash_t ht, hurd_ihash_key_t key)
do
{
up_idx = (up_idx + i) % ht->size;
- if (ht->items[up_idx].value == _HURD_IHASH_EMPTY
- || ht->items[up_idx].key == key)
+ if (VALUE (ht, up_idx) == _HURD_IHASH_EMPTY
+ || KEY (ht, up_idx) == key)
return up_idx;
if (down_idx < i)
down_idx += ht->size;
down_idx = (down_idx - i) % ht->size;
- if (ht->items[down_idx].value == _HURD_IHASH_EMPTY
- || ht->items[down_idx].key == key)
+ if (VALUE (ht, down_idx) == _HURD_IHASH_EMPTY
+ || KEY (ht, down_idx) == key)
return down_idx;
/* After (ht->size - 1) / 2 iterations, this will be 0. */
@@ -167,8 +187,11 @@ locp_remove (hurd_ihash_t ht, hurd_ihash_locp_t locp, bool cleanup)
/* Initialize the hash table at address HT. */
static void
-hurd_ihash_init_internal (hurd_ihash_t ht, intptr_t locp_offs)
+hurd_ihash_init_internal (hurd_ihash_t ht, bool large, intptr_t locp_offs)
{
+#if __WORDSIZE == 32
+ ht->large = large;
+#endif
ht->nr_items = 0;
ht->size = 0;
ht->locp_offset = locp_offs;
@@ -178,19 +201,20 @@ hurd_ihash_init_internal (hurd_ihash_t ht, intptr_t locp_offs)
#ifndef NO_MALLOC
void
-hurd_ihash_init (hurd_ihash_t ht, intptr_t locp_offs)
+hurd_ihash_init (hurd_ihash_t ht, bool large, intptr_t locp_offs)
{
- hurd_ihash_init_internal (ht, locp_offs);
+ hurd_ihash_init_internal (ht, large, locp_offs);
}
#endif
void
-hurd_ihash_init_with_buffer (hurd_ihash_t ht, intptr_t locp_offs,
+hurd_ihash_init_with_buffer (hurd_ihash_t ht, bool large,
+ intptr_t locp_offs,
void *buffer, size_t size)
{
- hurd_ihash_init_internal (ht, locp_offs);
+ hurd_ihash_init_internal (ht, large, locp_offs);
ht->items = buffer;
- ht->size = size / sizeof (struct _hurd_ihash_item);
+ ht->size = size / ITEM_SIZE (_HURD_IHASH_LARGE (ht));
}
@@ -220,13 +244,13 @@ hurd_ihash_destroy (hurd_ihash_t ht)
memory allocation error occurs, ENOMEM is returned, otherwise 0. */
#ifndef NO_MALLOC
error_t
-hurd_ihash_create (hurd_ihash_t *ht, intptr_t locp_offs)
+hurd_ihash_create (hurd_ihash_t *ht, bool large, intptr_t locp_offs)
{
*ht = malloc (sizeof (struct hurd_ihash));
if (*ht == NULL)
return ENOMEM;
- hurd_ihash_init (*ht, locp_offs);
+ hurd_ihash_init (*ht, large, locp_offs);
return 0;
}
@@ -284,7 +308,7 @@ hurd_ihash_set_max_load (hurd_ihash_t ht, unsigned int max_load)
division method with quadratic probe. This is guaranteed to try
all slots in the hash table if the prime number is 3 mod 4. */
static inline int
-replace_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value,
+replace_one (hurd_ihash_t ht, hurd_ihash_key64_t key, hurd_ihash_value_t value,
bool *had_value, hurd_ihash_value_t *old_value)
{
unsigned int idx;
@@ -293,7 +317,7 @@ replace_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value,
idx = key % ht->size;
first_free = idx;
- if (ht->items[idx].value != _HURD_IHASH_EMPTY && ht->items[idx].key != key)
+ if (VALUE (ht, idx) != _HURD_IHASH_EMPTY && KEY (ht, idx) != key)
{
/* Instead of calculating idx + 1, idx + 4, idx + 9, ..., idx +
i^2, we add 1, 3, 5, 7, ... 2 * i - 1 to the previous index.
@@ -305,14 +329,14 @@ replace_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value,
do
{
up_idx = (up_idx + i) % ht->size;
- if (ht->items[up_idx].value == _HURD_IHASH_EMPTY
- || ht->items[up_idx].key == key)
+ if (VALUE (ht, up_idx) == _HURD_IHASH_EMPTY
+ || KEY (ht, up_idx) == key)
{
idx = up_idx;
break;
}
if (first_free == idx
- && ht->items[up_idx].value == _HURD_IHASH_DELETED)
+ && VALUE (ht, up_idx) == _HURD_IHASH_DELETED)
first_free = up_idx;
if (down_idx < i)
@@ -322,14 +346,14 @@ replace_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value,
down_idx += ht->size;
else
down_idx %= ht->size;
- if (ht->items[down_idx].value == _HURD_IHASH_EMPTY
- || ht->items[down_idx].key == key)
+ if (VALUE (ht, down_idx) == _HURD_IHASH_EMPTY
+ || KEY (ht, down_idx) == key)
{
idx = down_idx;
break;
}
if (first_free == idx
- && ht->items[down_idx].value == _HURD_IHASH_DELETED)
+ && VALUE (ht, down_idx) == _HURD_IHASH_DELETED)
first_free = down_idx;
/* After (ht->size - 1) / 2 iterations, this will be 0. */
@@ -345,8 +369,8 @@ replace_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value,
*had_value = true;
if (old_value)
- *old_value = ht->items[idx].value;
- locp_remove (ht, &ht->items[idx].value, !! old_value);
+ *old_value = VALUE (ht, idx);
+ locp_remove (ht, ITEM (ht, idx), !! old_value);
}
else
{
@@ -362,12 +386,27 @@ replace_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value,
if (index_empty (ht, first_free))
{
ht->nr_items++;
- ht->items[first_free].value = value;
- ht->items[first_free].key = key;
- if (ht->locp_offset != HURD_IHASH_NO_LOCP)
- *((hurd_ihash_locp_t) (((char *) value) + ht->locp_offset))
- = &ht->items[first_free].value;
+ if (_HURD_IHASH_LARGE (ht))
+ {
+ _hurd_ihash_item64_t i = ITEM (ht, first_free);
+ i->value = value;
+ i->key = key;
+
+ if (ht->locp_offset != HURD_IHASH_NO_LOCP)
+ *((hurd_ihash_locp_t) (((char *) value) + ht->locp_offset))
+ = &i->value;
+ }
+ else
+ {
+ _hurd_ihash_item_t i = ITEM (ht, first_free);
+ i->value = value;
+ i->key = key;
+
+ if (ht->locp_offset != HURD_IHASH_NO_LOCP)
+ *((hurd_ihash_locp_t) (((char *) value) + ht->locp_offset))
+ = &i->value;
+ }
return 1;
}
@@ -380,7 +419,7 @@ replace_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value,
(LOAD_FACTOR must be between 1 and 100, a load factor of 0 implies
the default load factor). */
size_t
-hurd_ihash_buffer_size (size_t count, int max_load_factor)
+hurd_ihash_buffer_size (size_t count, bool large, int max_load_factor)
{
if (max_load_factor == 0)
max_load_factor = HURD_IHASH_MAX_LOAD_DEFAULT;
@@ -398,7 +437,7 @@ hurd_ihash_buffer_size (size_t count, int max_load_factor)
if (i == ihash_nsizes)
return SIZE_MAX; /* Surely will be true momentarily. */
- return ihash_sizes[i] * sizeof (struct _hurd_ihash_item);
+ return ihash_sizes[i] * ITEM_SIZE (large);
}
/* Add ITEM to the hash table HT under the key KEY. If there already
@@ -410,7 +449,7 @@ hurd_ihash_buffer_size (size_t count, int max_load_factor)
*HAD_VALUE. If a memory allocation error occurs, ENOMEM is
returned, otherwise 0. */
error_t
-hurd_ihash_replace (hurd_ihash_t ht, hurd_ihash_key_t key,
+hurd_ihash_replace (hurd_ihash_t ht, hurd_ihash_key64_t key,
hurd_ihash_value_t item,
bool *had_value, hurd_ihash_value_t *old_value)
{
@@ -432,14 +471,16 @@ hurd_ihash_replace (hurd_ihash_t ht, hurd_ihash_key_t key,
int i;
/* The hash table is too small, and we have to increase it. */
- size_t size = hurd_ihash_buffer_size (old_ht.size + 1, ht->max_load);
+ size_t size = hurd_ihash_buffer_size (old_ht.size + 1,
+ _HURD_IHASH_LARGE (ht),
+ ht->max_load);
if (size >= SIZE_MAX)
return ENOMEM; /* Surely will be true momentarily. */
ht->nr_items = 0;
- ht->size = size / sizeof (struct _hurd_ihash_item);
+ ht->size = size / ITEM_SIZE (_HURD_IHASH_LARGE (ht));
/* calloc() will initialize all values to _HURD_IHASH_EMPTY implicitely. */
- ht->items = calloc (ht->size, sizeof (struct _hurd_ihash_item));
+ ht->items = calloc (ht->size, ITEM_SIZE (_HURD_IHASH_LARGE (ht)));
if (ht->items == NULL)
{
@@ -454,8 +495,7 @@ hurd_ihash_replace (hurd_ihash_t ht, hurd_ihash_key_t key,
for (i = 0; i < old_ht.size; i++)
if (!index_empty (&old_ht, i))
{
- was_added = replace_one (ht, old_ht.items[i].key,
- old_ht.items[i].value,
+ was_added = replace_one (ht, KEY (&old_ht, i), VALUE (&old_ht, i),
had_value, old_value);
assert (was_added);
}
@@ -475,14 +515,14 @@ hurd_ihash_replace (hurd_ihash_t ht, hurd_ihash_key_t key,
/* Find and return the item in the hash table HT with key KEY, or NULL
if it doesn't exist. */
hurd_ihash_value_t
-hurd_ihash_find (hurd_ihash_t ht, hurd_ihash_key_t key)
+hurd_ihash_find (hurd_ihash_t ht, hurd_ihash_key64_t key)
{
if (ht->size == 0)
return NULL;
else
{
int idx = find_index (ht, key);
- return index_valid (ht, idx, key) ? ht->items[idx].value : NULL;
+ return index_valid (ht, idx, key) ? VALUE (ht, idx) : NULL;
}
}
@@ -490,7 +530,7 @@ hurd_ihash_find (hurd_ihash_t ht, hurd_ihash_key_t key)
/* Remove the entry with the key KEY from the hash table HT. If such
an entry was found and removed, 1 is returned, otherwise 0. */
int
-hurd_ihash_remove (hurd_ihash_t ht, hurd_ihash_key_t key)
+hurd_ihash_remove (hurd_ihash_t ht, hurd_ihash_key64_t key)
{
if (ht->size != 0)
{
@@ -498,7 +538,7 @@ hurd_ihash_remove (hurd_ihash_t ht, hurd_ihash_key_t key)
if (index_valid (ht, idx, key))
{
- locp_remove (ht, &ht->items[idx].value, true);
+ locp_remove (ht, ITEM (ht, idx), true);
return 1;
}
}
diff --git a/libhurd-ihash/ihash.h b/libhurd-ihash/ihash.h
index c2332de..95e022c 100644
--- a/libhurd-ihash/ihash.h
+++ b/libhurd-ihash/ihash.h
@@ -27,6 +27,17 @@
#include <limits.h>
#include <stdint.h>
#include <stdbool.h>
+/* If your system does not provide __WORDSIZE, you can also try
+ deriving it via <stdint.h>:
+
+ #if UINT64_MAX == UINTPTR_MAX
+ # define __WORDSIZE 64
+ #else
+ # define __WORDSIZE 32
+ #endif
+
+ Depending on how the constants are derived this might not work. */
+#include <bits/wordsize.h>
/* The type of the values corresponding to the keys. Must be a
@@ -44,6 +55,7 @@ typedef void *hurd_ihash_value_t;
/* The type of integer we want to use for the keys. */
typedef uintptr_t hurd_ihash_key_t;
+typedef uint64_t hurd_ihash_key64_t;
/* The type of a location pointer, which is a pointer to the hash
value stored in the hash table. */
@@ -66,15 +78,37 @@ struct _hurd_ihash_item
};
typedef struct _hurd_ihash_item *_hurd_ihash_item_t;
+struct _hurd_ihash_item64
+{
+ /* The value of this hash item. Must be the first element of
+ the struct for the HURD_IHASH_ITERATE macro. */
+ hurd_ihash_value_t value;
+
+ /* The integer key of this hash item. */
+ hurd_ihash_key64_t key;
+};
+typedef struct _hurd_ihash_item64 *_hurd_ihash_item64_t;
+
struct hurd_ihash
{
/* The number of hashed elements. */
size_t nr_items;
- /* An array of (key, value) pairs. */
- _hurd_ihash_item_t items;
-
- /* The length of the array ITEMS. */
+#if __WORDSIZE == 32
+ /* Whether items is an array consisting of _hurd_ihash_item_t or
+ _hurd_ihash_item64_t elements. */
+ bool large;
+# define _HURD_IHASH_LARGE(ht) ((ht)->large)
+#else
+ /* The machine word size is 64-bits. */
+# define _HURD_IHASH_LARGE(ht) (false)
+#endif
+
+ /* An array of (key, value) pairs (either _hurd_ihash_item_t or
+ _hurd_ihash_item64_t). */
+ void *items;
+
+ /* The length of the array ITEMS (in number of items, not bytes). */
size_t size;
/* The offset of the location pointer from the hash value. */
@@ -101,30 +135,42 @@ typedef struct hurd_ihash *hurd_ihash_t;
#define HURD_IHASH_NO_LOCP PTRDIFF_MIN
/* The static initializer for a struct hurd_ihash. */
-#define HURD_IHASH_INITIALIZER(locp_offs) \
+#if __WORDSIZE == 32
+#define HURD_IHASH_INITIALIZER(locp_offs, large) \
{ .nr_items = 0, .size = 0, .cleanup = (hurd_ihash_cleanup_t) 0, \
.max_load = HURD_IHASH_MAX_LOAD_DEFAULT, \
- .locp_offset = (locp_offs)}
-
-/* Initialize the hash table at address HT. If LOCP_OFFSET is not
- HURD_IHASH_NO_LOCP, then this is an offset (in bytes) from the
- address of a hash value where a location pointer can be found. The
- location pointer must be of type hurd_ihash_locp_t and can be used
- for fast removal with hurd_ihash_locp_remove(). This function is
- not provided if compiled with NO_MALLOC. */
-void hurd_ihash_init (hurd_ihash_t ht, intptr_t locp_offs);
+ .locp_offset = (locp_offs), large = (large) }
+#else
+#define HURD_IHASH_INITIALIZER(locp_offs, large) \
+ { .nr_items = 0, .size = 0, .cleanup = (hurd_ihash_cleanup_t) 0, \
+ .max_load = HURD_IHASH_MAX_LOAD_DEFAULT, \
+ .locp_offset = (locp_offs) }
+#endif
+/* Initialize the hash table at address HT. LARGE determines whether
+ the hash should uses 64-bit or machine word sized keys. If
+ LOCP_OFFSET is not HURD_IHASH_NO_LOCP, then this is an offset (in
+ bytes) from the address of a hash value where a location pointer
+ can be found. The location pointer must be of type
+ hurd_ihash_locp_t and can be used for fast removal with
+ hurd_ihash_locp_remove(). This function is not provided if
+ compiled with NO_MALLOC. */
+void hurd_ihash_init (hurd_ihash_t ht, bool large, intptr_t locp_offs);
/* Return the size of a buffer (in bytes) that is appropriate for a
- hash with COUNT elements and a load factor of LOAD_FACTOR
+ hash with COUNT elements, if LARGE, with 64-bit keys, otherwise
+ with machine-word sized keys, and a load factor of LOAD_FACTOR
(LOAD_FACTOR must be between 1 and 100, a load factor of 0 implies
the default load factor). */
-size_t hurd_ihash_buffer_size (size_t count, int max_load_factor);
+size_t hurd_ihash_buffer_size (size_t count, bool large, int max_load_factor);
/* Initialize a hash ala hurd_ihash_init but provide an initial buffer
- BUFFER of size SIZE bytes. If not compiled with NO_MALLOC, the
- memory is assumed to be allocated with malloc and may be freed if
- the hash must be grown or when hurd_ihash_destroy is called. */
-void hurd_ihash_init_with_buffer (hurd_ihash_t ht, intptr_t locp_offs,
+ BUFFER of size SIZE bytes. LARGE determines whether the hash
+ should uses 64-bit or machine word sized keys. If not compiled
+ with NO_MALLOC, the memory is assumed to be allocated with malloc
+ and may be freed if the hash must be grown or when
+ hurd_ihash_destroy is called. */
+void hurd_ihash_init_with_buffer (hurd_ihash_t ht, bool large,
+ intptr_t locp_offs,
void *buffer, size_t size);
/* Destroy the hash table at address HT. This first removes all
@@ -134,15 +180,17 @@ void hurd_ihash_init_with_buffer (hurd_ihash_t ht, intptr_t locp_offs,
otherwise, any buffer in use if freed. */
void hurd_ihash_destroy (hurd_ihash_t ht);
-/* Create a hash table, initialize it and return it in HT. If
- LOCP_OFFSET is not HURD_IHASH_NO_LOCP, then this is an offset (in
- bytes) from the address of a hash value where a location pointer
- can be found. The location pointer must be of type
- hurd_ihash_locp_t and can be used for fast removal with
+/* Create a hash table, initialize it and return it in HT. LARGE
+ determines whether the hash should uses 64-bit or machine word
+ sized keys. If LOCP_OFFSET is not HURD_IHASH_NO_LOCP, then this is
+ an offset (in bytes) from the address of a hash value where a
+ location pointer can be found. The location pointer must be of
+ type hurd_ihash_locp_t and can be used for fast removal with
hurd_ihash_locp_remove(). If a memory allocation error occurs,
ENOMEM is returned, otherwise 0. This function is not provided if
compiled with NO_MALLOC. */
-error_t hurd_ihash_create (hurd_ihash_t *ht, intptr_t locp_offs);
+error_t hurd_ihash_create (hurd_ihash_t *ht, bool large,
+ intptr_t locp_offs);
/* Destroy the hash table HT and release the memory allocated for it
by hurd_ihash_create(). This function is not provided if compiled
@@ -182,7 +230,7 @@ void hurd_ihash_set_max_load (hurd_ihash_t ht, unsigned int max_load);
*HAD_VALUE. If a memory allocation error occurs, ENOMEM is
returned, otherwise 0. */
error_t
-hurd_ihash_replace (hurd_ihash_t ht, hurd_ihash_key_t key,
+hurd_ihash_replace (hurd_ihash_t ht, hurd_ihash_key64_t key,
hurd_ihash_value_t item,
bool *had_value, hurd_ihash_value_t *old_value);
@@ -191,7 +239,7 @@ hurd_ihash_replace (hurd_ihash_t ht, hurd_ihash_key_t key,
it before overriding the value. If a memory allocation error
occurs, ENOMEM is returned, otherwise 0. */
static inline error_t
-hurd_ihash_add (hurd_ihash_t ht, hurd_ihash_key_t key,
+hurd_ihash_add (hurd_ihash_t ht, hurd_ihash_key64_t key,
hurd_ihash_value_t item)
{
return hurd_ihash_replace (ht, key, item, NULL, NULL);
@@ -199,7 +247,7 @@ hurd_ihash_add (hurd_ihash_t ht, hurd_ihash_key_t key,
/* Find and return the item in the hash table HT with key KEY, or NULL
if it doesn't exist. */
-hurd_ihash_value_t hurd_ihash_find (hurd_ihash_t ht, hurd_ihash_key_t key);
+hurd_ihash_value_t hurd_ihash_find (hurd_ihash_t ht, hurd_ihash_key64_t key);
/* Iterate over all elements in the hash table. You use this macro
with a block, for example like this:
@@ -245,18 +293,21 @@ hurd_ihash_value_t hurd_ihash_find (hurd_ihash_t ht, hurd_ihash_key_t key);
subexpression is always true). */
#define HURD_IHASH_ITERATE(ht, val) \
for (hurd_ihash_value_t val, \
- *_hurd_ihash_valuep = (ht)->size ? &(ht)->items[0].value : 0; \
- (ht)->size \
- && ((_hurd_ihash_item_t) _hurd_ihash_valuep) - &(ht)->items[0] \
- < (ht)->size \
+ *_hurd_ihash_valuep = (ht)->items; \
+ ((void *) _hurd_ihash_valuep \
+ < (ht)->items + (ht)->size * (_HURD_IHASH_LARGE (ht) \
+ ? sizeof (struct _hurd_ihash_item64) \
+ : sizeof (struct _hurd_ihash_item))) \
&& (val = *_hurd_ihash_valuep, 1); \
_hurd_ihash_valuep = (hurd_ihash_value_t *) \
- (((_hurd_ihash_item_t) _hurd_ihash_valuep) + 1)) \
+ (_HURD_IHASH_LARGE (ht) \
+ ? (void *) (((_hurd_ihash_item64_t) _hurd_ihash_valuep) + 1) \
+ : (void *) (((_hurd_ihash_item_t) _hurd_ihash_valuep) + 1))) \
if (val != _HURD_IHASH_EMPTY && val != _HURD_IHASH_DELETED)
/* Remove the entry with the key KEY from the hash table HT. If such
an entry was found and removed, 1 is returned, otherwise 0. */
-int hurd_ihash_remove (hurd_ihash_t ht, hurd_ihash_key_t key);
+int hurd_ihash_remove (hurd_ihash_t ht, hurd_ihash_key64_t key);
/* Remove from the hast table HT the entry with the location pointer
LOCP. That is, if the location pointer is stored in a field named
diff --git a/libhurd-ihash/t-ihash.c b/libhurd-ihash/t-ihash.c
index 56cb32e..e71ba95 100644
--- a/libhurd-ihash/t-ihash.c
+++ b/libhurd-ihash/t-ihash.c
@@ -1,5 +1,5 @@
/* t-ihash.c - Integer-keyed hash table function unit-tests.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2008 Free Software Foundation, Inc.
Written by Neal H. Walfield <neal@gnu.org>.
This file is part of the GNU Hurd.
@@ -21,6 +21,7 @@
#define _GNU_SOURCE
#include <stdio.h>
+#include <assert.h>
const char program_name[] = "t-ihash";
@@ -45,7 +46,7 @@ main (int argc, char *argv[])
{
struct hurd_ihash hash;
- hurd_ihash_init (&hash, HURD_IHASH_NO_LOCP);
+ hurd_ihash_init (&hash, TEST_LARGE, HURD_IHASH_NO_LOCP);
printf ("Testing hurd_ihash_add... ");
@@ -55,12 +56,35 @@ main (int argc, char *argv[])
if (hurd_ihash_add (&hash, (hurd_ihash_key_t) k,
(hurd_ihash_value_t) k) != 0)
F ("failed to insert %d\n", k);
+#if TEST_LARGE == true
+ for (k = 1; k < 100; k ++)
+ if (hurd_ihash_add (&hash, (hurd_ihash_key64_t) (1ULL << 33) + k,
+ (hurd_ihash_value_t) (1000 + k)) != 0)
+ F ("failed to insert %d\n", k);
+#endif
for (k = 1; k < 100; k ++)
{
v = hurd_ihash_find (&hash, (hurd_ihash_key_t) k);
if (v != (hurd_ihash_value_t) k)
F ("unexpected value %d for key %d\n", (int) v, k);
}
+#if TEST_LARGE == true
+ for (k = 1; k < 100; k ++)
+ {
+ v = hurd_ihash_find (&hash, (hurd_ihash_key64_t) (1ULL << 33) + k);
+ if (v != (hurd_ihash_value_t) (1000 + k))
+ F ("unexpected value %d for key %d\n", (int) v, 1000 + k);
+ }
+#endif
+
+ int c = 0;
+ HURD_IHASH_ITERATE(&hash, i)
+ c ++;
+#if TEST_LARGE == true
+ assert (c == 2 * 99);
+#else
+ assert (c == 99);
+#endif
printf ("ok\n");
@@ -106,7 +130,7 @@ main (int argc, char *argv[])
int value;
hurd_ihash_locp_t locp;
};
- hurd_ihash_init (&hash, (int) &(((struct s *)0)->locp));
+ hurd_ihash_init (&hash, TEST_LARGE, (int) &(((struct s *)0)->locp));
if (hurd_ihash_find (&hash, 1))
F ("Found object with key 1 in otherwise empty hash");