summaryrefslogtreecommitdiff
path: root/debian/patches/ihash-as-cache0003-libihash-generalize-the-interface-to-support-non-int.patch
blob: fbadb8056dee6d3c6abf08fb67202f22e2fec556 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
From 99833334867f052e6ad98ec4b6a72bbabf4362c4 Mon Sep 17 00:00:00 2001
From: Justus Winter <4winter@informatik.uni-hamburg.de>
Date: Sat, 21 Nov 2015 16:27:40 +0100
Subject: [PATCH hurd 3/5] libihash: generalize the interface to support
 non-integer keys

* libihash/ihash.c (hash, compare): New functions that are used
throughout libihash to hash and compare keys.
(hurd_ihash_set_gki): New function.
* libihash/ihash.h (hurd_ihash_fct_hash_t): New type for hash functions.
(hurd_ihash_fct_cmp_t): New type for comparison functions.
(struct hurd_ihash): New fields for hash and comparison functions.
(HURD_IHASH_INITIALIZER_GKI): New static initializer.
(hurd_ihash_set_gki): New prototype.
---
 libihash/ihash.c | 59 +++++++++++++++++++++++++++++++++++++++++++++-----------
 libihash/ihash.h | 36 +++++++++++++++++++++++++++++++++-
 2 files changed, 83 insertions(+), 12 deletions(-)

diff --git a/libihash/ihash.c b/libihash/ihash.c
index 598d341..164b84d 100644
--- a/libihash/ihash.c
+++ b/libihash/ihash.c
@@ -1,5 +1,5 @@
 /* ihash.c - Integer-keyed hash table functions.
-   Copyright (C) 1993-1997, 2001, 2003, 2004, 2006
+   Copyright (C) 1993-1997, 2001, 2003, 2004, 2006, 2014, 2015
      Free Software Foundation, Inc.
    Written by Michael I. Bushnell.
    Revised by Miles Bader <miles@gnu.org>.
@@ -32,6 +32,22 @@
 
 #include "ihash.h"
 
+/* This function is used to hash the key.  */
+static inline hurd_ihash_key_t
+hash (hurd_ihash_t ht, hurd_ihash_key_t k)
+{
+  return ht->fct_hash ? ht->fct_hash ((void *) k) : k;
+}
+
+/* This function is used to compare the key.  Returns true if A is
+   equal to B.  */
+static inline int
+compare (hurd_ihash_t ht, hurd_ihash_key_t a, hurd_ihash_key_t b)
+{
+  return
+    ht->fct_cmp ? (a && ht->fct_cmp ((void *) a, (void *) b)) : a == b;
+}
+
 /* Return 1 if the slot with the index IDX in the hash table HT is
    empty, and 0 otherwise.  */
 static inline int
@@ -46,7 +62,7 @@ index_empty (hurd_ihash_t ht, unsigned int idx)
 static inline int
 index_valid (hurd_ihash_t ht, unsigned int idx, hurd_ihash_key_t key)
 {
-  return !index_empty (ht, idx) && ht->items[idx].key == key;
+  return !index_empty (ht, idx) && compare (ht, ht->items[idx].key, key);
 }
 
 
@@ -60,9 +76,10 @@ find_index (hurd_ihash_t ht, hurd_ihash_key_t key)
   unsigned int up_idx;
   unsigned int mask = ht->size - 1;
 
-  idx = key & mask;
+  idx = hash (ht, key) & mask;
 
-  if (ht->items[idx].value == _HURD_IHASH_EMPTY || ht->items[idx].key == key)
+  if (ht->items[idx].value == _HURD_IHASH_EMPTY
+      || compare (ht, ht->items[idx].key, key))
     return idx;
 
   up_idx = idx;
@@ -71,7 +88,7 @@ find_index (hurd_ihash_t ht, hurd_ihash_key_t key)
     {
       up_idx = (up_idx + 1) & mask;
       if (ht->items[up_idx].value == _HURD_IHASH_EMPTY
-	  || ht->items[up_idx].key == key)
+	  || compare (ht, ht->items[up_idx].key, key))
 	return up_idx;
     }
   while (up_idx != idx);
@@ -88,9 +105,11 @@ find_index (hurd_ihash_t ht, hurd_ihash_key_t key)
 static inline void
 locp_remove (hurd_ihash_t ht, hurd_ihash_locp_t locp)
 {
+  struct _hurd_ihash_item *item = locp;
   if (ht->cleanup)
-    (*ht->cleanup) (*locp, ht->cleanup_data);
-  *locp = _HURD_IHASH_DELETED;
+    (*ht->cleanup) (item->value, ht->cleanup_data);
+  item->value = _HURD_IHASH_DELETED;
+  item->key = 0;
   ht->nr_items--;
 }
 
@@ -106,6 +125,8 @@ hurd_ihash_init (hurd_ihash_t ht, intptr_t locp_offs)
   ht->locp_offset = locp_offs;
   ht->max_load = HURD_IHASH_MAX_LOAD_DEFAULT;
   ht->cleanup = 0;
+  ht->fct_hash = NULL;
+  ht->fct_cmp = NULL;
 }
 
 
@@ -166,6 +187,21 @@ hurd_ihash_set_cleanup (hurd_ihash_t ht, hurd_ihash_cleanup_t cleanup,
 }
 
 
+/* Use the generalized key interface.  Must be called before any item
+   is inserted into the table.  */
+void
+hurd_ihash_set_gki (hurd_ihash_t ht,
+		    hurd_ihash_fct_hash_t fct_hash,
+		    hurd_ihash_fct_cmp_t fct_cmp)
+{
+  assert (ht->size == 0 || !"called after insertion");
+  assert (fct_hash);
+  assert (fct_cmp);
+  ht->fct_hash = fct_hash;
+  ht->fct_cmp = fct_cmp;
+}
+
+
 /* Set the maximum load factor in binary percent to MAX_LOAD, which
    should be between 64 and 128.  The default is
    HURD_IHASH_MAX_LOAD_DEFAULT.  New elements are only added to the
@@ -199,10 +235,11 @@ add_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value)
   unsigned int first_free;
   unsigned int mask = ht->size - 1;
 
-  idx = key & mask;
+  idx = hash (ht, key) & mask;
   first_free = idx;
 
-  if (ht->items[idx].value != _HURD_IHASH_EMPTY && ht->items[idx].key != key)
+  if (ht->items[idx].value != _HURD_IHASH_EMPTY
+      && ! compare (ht, ht->items[idx].key, key))
     {
       unsigned int up_idx = idx;
 
@@ -210,7 +247,7 @@ add_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value)
 	{
         up_idx = (up_idx + 1) & mask;
 	  if (ht->items[up_idx].value == _HURD_IHASH_EMPTY
-	      || ht->items[up_idx].key == key)
+	      || compare (ht, ht->items[up_idx].key, key))
 	    {
 	      idx = up_idx;
 	      break;
@@ -278,7 +315,7 @@ hurd_ihash_locp_add (hurd_ihash_t ht, hurd_ihash_locp_t locp,
     }
   else
     {
-      assert (item->key == key);
+      assert (compare (ht, item->key, key));
       if (ht->cleanup)
         (*ht->cleanup) (locp, ht->cleanup_data);
     }
diff --git a/libihash/ihash.h b/libihash/ihash.h
index fdfc367..d332479 100644
--- a/libihash/ihash.h
+++ b/libihash/ihash.h
@@ -1,5 +1,5 @@
 /* ihash.h - Integer keyed hash table interface.
-   Copyright (C) 1995, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1995, 2003, 2004, 2014, 2015 Free Software Foundation, Inc.
    Written by Miles Bader <miles@gnu.org>.
    Revised by Marcus Brinkmann <marcus@gnu.org>.
 
@@ -57,6 +57,20 @@ typedef uintptr_t hurd_ihash_key_t;
 typedef hurd_ihash_value_t *hurd_ihash_locp_t;
 
 
+/* We support non-integer keys using the generalized key interface.
+
+   To use it, supply a pair of functions matching the following
+   specification, and use pointers to the key instead of the key
+   itself in all calls to libihash.  */
+
+/* The type of a function computing a hash for the given key.  */
+typedef hurd_ihash_key_t (*hurd_ihash_fct_hash_t) (void *);
+
+/* The type of a function comparing two given keys.  Return true if
+   both keys are equal.  */
+typedef int (*hurd_ihash_fct_cmp_t) (void *, void *);
+
+
 /* The type of the cleanup function, which is called for every value
    removed from the hash table.  */
 typedef void (*hurd_ihash_cleanup_t) (hurd_ihash_value_t value, void *arg);
@@ -95,6 +109,10 @@ struct hurd_ihash
      second argument.  This does not happen if CLEANUP is NULL.  */
   hurd_ihash_cleanup_t cleanup;
   void *cleanup_data;
+
+  /* User-supplied functions for the generalized key interface.  */
+  hurd_ihash_fct_hash_t fct_hash;
+  hurd_ihash_fct_cmp_t fct_cmp;
 };
 typedef struct hurd_ihash *hurd_ihash_t;
 
@@ -118,6 +136,16 @@ typedef struct hurd_ihash *hurd_ihash_t;
     .max_load = HURD_IHASH_MAX_LOAD_DEFAULT,				\
     .locp_offset = (locp_offs)}
 
+#define HURD_IHASH_INITIALIZER_GKI(locp_offs, f_clean, f_clean_data,	\
+				   f_hash, f_compare)			\
+  { .nr_items = 0, .size = 0,						\
+    .cleanup = (f_clean),						\
+    .cleanup_data = (f_clean_data),					\
+    .max_load = HURD_IHASH_MAX_LOAD_DEFAULT,				\
+    .locp_offset = (locp_offs),						\
+    .fct_hash = (f_hash),						\
+    .fct_cmp = (f_compare)}						\
+
 /* 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
@@ -152,6 +180,12 @@ void hurd_ihash_free (hurd_ihash_t ht);
 void hurd_ihash_set_cleanup (hurd_ihash_t ht, hurd_ihash_cleanup_t cleanup,
 			     void *cleanup_data);
 
+/* Use the generalized key interface.  Must be called before any item
+   is inserted into the table.	*/
+void hurd_ihash_set_gki (hurd_ihash_t ht,
+			 hurd_ihash_fct_hash_t fct_hash,
+			 hurd_ihash_fct_cmp_t fct_cmp);
+
 /* Set the maximum load factor in binary percent to MAX_LOAD, which
    should be between 64 and 128.  The default is
    HURD_IHASH_MAX_LOAD_DEFAULT.  New elements are only added to the
-- 
2.1.4