]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/hash-table.h
Remove a layer of indirection from hash_table
[thirdparty/gcc.git] / gcc / hash-table.h
CommitLineData
0823efed 1/* A type-safe hash table template.
23a5b65a 2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
0823efed
DN
3 Contributed by Lawrence Crowl <crowl@google.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21
22/* This file implements a typed hash table.
5831a5f0
LC
23 The implementation borrows from libiberty's htab_t in hashtab.h.
24
25
26 INTRODUCTION TO TYPES
27
28 Users of the hash table generally need to be aware of three types.
29
30 1. The type being placed into the hash table. This type is called
31 the value type.
32
33 2. The type used to describe how to handle the value type within
34 the hash table. This descriptor type provides the hash table with
35 several things.
36
37 - A typedef named 'value_type' to the value type (from above).
38
39 - A static member function named 'hash' that takes a value_type
40 pointer and returns a hashval_t value.
41
42 - A typedef named 'compare_type' that is used to test when an value
43 is found. This type is the comparison type. Usually, it will be the
44 same as value_type. If it is not the same type, you must generally
45 explicitly compute hash values and pass them to the hash table.
46
47 - A static member function named 'equal' that takes a value_type
48 pointer and a compare_type pointer, and returns a bool.
49
50 - A static function named 'remove' that takes an value_type pointer
51 and frees the memory allocated by it. This function is used when
52 individual elements of the table need to be disposed of (e.g.,
53 when deleting a hash table, removing elements from the table, etc).
54
55 3. The type of the hash table itself. (More later.)
56
57 In very special circumstances, users may need to know about a fourth type.
58
59 4. The template type used to describe how hash table memory
60 is allocated. This type is called the allocator type. It is
61 parameterized on the value type. It provides four functions.
62
5831a5f0
LC
63 - A static member function named 'data_alloc'. This function
64 allocates the data elements in the table.
65
66 - A static member function named 'data_free'. This function
67 deallocates the data elements in the table.
68
69 Hash table are instantiated with two type arguments.
70
71 * The descriptor type, (2) above.
72
73 * The allocator type, (4) above. In general, you will not need to
74 provide your own allocator type. By default, hash tables will use
75 the class template xcallocator, which uses malloc/free for allocation.
76
77
78 DEFINING A DESCRIPTOR TYPE
79
80 The first task in using the hash table is to describe the element type.
81 We compose this into a few steps.
82
83 1. Decide on a removal policy for values stored in the table.
84 This header provides class templates for the two most common
85 policies.
86
87 * typed_free_remove implements the static 'remove' member function
88 by calling free().
89
90 * typed_noop_remove implements the static 'remove' member function
91 by doing nothing.
92
93 You can use these policies by simply deriving the descriptor type
94 from one of those class template, with the appropriate argument.
95
96 Otherwise, you need to write the static 'remove' member function
97 in the descriptor class.
98
99 2. Choose a hash function. Write the static 'hash' member function.
100
101 3. Choose an equality testing function. In most cases, its two
102 arguments will be value_type pointers. If not, the first argument must
103 be a value_type pointer, and the second argument a compare_type pointer.
104
105
106 AN EXAMPLE DESCRIPTOR TYPE
107
108 Suppose you want to put some_type into the hash table. You could define
109 the descriptor type as follows.
110
111 struct some_type_hasher : typed_noop_remove <some_type>
112 // Deriving from typed_noop_remove means that we get a 'remove' that does
113 // nothing. This choice is good for raw values.
114 {
115 typedef some_type value_type;
116 typedef some_type compare_type;
117 static inline hashval_t hash (const value_type *);
118 static inline bool equal (const value_type *, const compare_type *);
119 };
120
121 inline hashval_t
122 some_type_hasher::hash (const value_type *e)
123 { ... compute and return a hash value for E ... }
124
125 inline bool
126 some_type_hasher::equal (const value_type *p1, const compare_type *p2)
127 { ... compare P1 vs P2. Return true if they are the 'same' ... }
128
129
130 AN EXAMPLE HASH_TABLE DECLARATION
131
132 To instantiate a hash table for some_type:
133
134 hash_table <some_type_hasher> some_type_hash_table;
135
136 There is no need to mention some_type directly, as the hash table will
137 obtain it using some_type_hasher::value_type.
138
139 You can then used any of the functions in hash_table's public interface.
140 See hash_table for details. The interface is very similar to libiberty's
141 htab_t.
142
143
144 EASY DESCRIPTORS FOR POINTERS
145
146 The class template pointer_hash provides everything you need to hash
147 pointers (as opposed to what they point to). So, to instantiate a hash
148 table over pointers to whatever_type,
149
150 hash_table <pointer_hash <whatever_type>> whatever_type_hash_table;
151
bf190e8d
LC
152
153 HASH TABLE ITERATORS
154
155 The hash table provides standard C++ iterators. For example, consider a
156 hash table of some_info. We wish to consume each element of the table:
157
158 extern void consume (some_info *);
159
160 We define a convenience typedef and the hash table:
161
162 typedef hash_table <some_info_hasher> info_table_type;
163 info_table_type info_table;
164
165 Then we write the loop in typical C++ style:
166
167 for (info_table_type::iterator iter = info_table.begin ();
168 iter != info_table.end ();
169 ++iter)
170 if ((*iter).status == INFO_READY)
171 consume (&*iter);
172
173 Or with common sub-expression elimination:
174
175 for (info_table_type::iterator iter = info_table.begin ();
176 iter != info_table.end ();
177 ++iter)
178 {
179 some_info &elem = *iter;
180 if (elem.status == INFO_READY)
181 consume (&elem);
182 }
183
184 One can also use a more typical GCC style:
185
186 typedef some_info *some_info_p;
187 some_info *elem_ptr;
188 info_table_type::iterator iter;
189 FOR_EACH_HASH_TABLE_ELEMENT (info_table, elem_ptr, some_info_p, iter)
190 if (elem_ptr->status == INFO_READY)
191 consume (elem_ptr);
192
5831a5f0 193*/
0823efed
DN
194
195
196#ifndef TYPED_HASHTAB_H
197#define TYPED_HASHTAB_H
198
199#include "hashtab.h"
200
201
202/* The ordinary memory allocator. */
203/* FIXME (crowl): This allocator may be extracted for wider sharing later. */
204
205template <typename Type>
206struct xcallocator
207{
0823efed 208 static Type *data_alloc (size_t count);
0823efed
DN
209 static void data_free (Type *memory);
210};
211
212
5831a5f0 213/* Allocate memory for COUNT data blocks. */
0823efed
DN
214
215template <typename Type>
216inline Type *
217xcallocator <Type>::data_alloc (size_t count)
218{
219 return static_cast <Type *> (xcalloc (count, sizeof (Type)));
220}
221
222
0823efed
DN
223/* Free memory for data blocks. */
224
225template <typename Type>
226inline void
227xcallocator <Type>::data_free (Type *memory)
228{
229 return ::free (memory);
230}
231
232
5831a5f0 233/* Helpful type for removing with free. */
0823efed 234
5831a5f0 235template <typename Type>
5deac340 236struct typed_free_remove
0823efed 237{
5831a5f0 238 static inline void remove (Type *p);
5deac340 239};
0823efed 240
0823efed 241
5831a5f0
LC
242/* Remove with free. */
243
244template <typename Type>
245inline void
246typed_free_remove <Type>::remove (Type *p)
247{
248 free (p);
249}
250
251
252/* Helpful type for a no-op remove. */
253
254template <typename Type>
5deac340 255struct typed_noop_remove
0823efed 256{
5831a5f0 257 static inline void remove (Type *p);
5deac340 258};
0823efed
DN
259
260
5831a5f0
LC
261/* Remove doing nothing. */
262
263template <typename Type>
264inline void
265typed_noop_remove <Type>::remove (Type *p ATTRIBUTE_UNUSED)
266{
267}
268
269
5deac340 270/* Pointer hash with a no-op remove method. */
0823efed 271
5831a5f0
LC
272template <typename Type>
273struct pointer_hash : typed_noop_remove <Type>
0823efed 274{
5831a5f0
LC
275 typedef Type value_type;
276 typedef Type compare_type;
0823efed 277
5deac340 278 static inline hashval_t
5831a5f0 279 hash (const value_type *);
0823efed 280
5deac340 281 static inline int
5831a5f0 282 equal (const value_type *existing, const compare_type *candidate);
5deac340 283};
0823efed 284
5831a5f0 285template <typename Type>
5deac340 286inline hashval_t
5831a5f0 287pointer_hash <Type>::hash (const value_type *candidate)
5deac340
RG
288{
289 /* This is a really poor hash function, but it is what the current code uses,
290 so I am reusing it to avoid an additional axis in testing. */
291 return (hashval_t) ((intptr_t)candidate >> 3);
292}
293
5831a5f0 294template <typename Type>
5deac340 295inline int
5831a5f0
LC
296pointer_hash <Type>::equal (const value_type *existing,
297 const compare_type *candidate)
0823efed 298{
5deac340 299 return existing == candidate;
0823efed
DN
300}
301
302
303/* Table of primes and their inversion information. */
304
305struct prime_ent
306{
307 hashval_t prime;
308 hashval_t inv;
309 hashval_t inv_m2; /* inverse of prime-2 */
310 hashval_t shift;
311};
312
313extern struct prime_ent const prime_tab[];
314
315
316/* Functions for computing hash table indexes. */
317
318extern unsigned int hash_table_higher_prime_index (unsigned long n);
319extern hashval_t hash_table_mod1 (hashval_t hash, unsigned int index);
320extern hashval_t hash_table_mod2 (hashval_t hash, unsigned int index);
321
322
0823efed
DN
323/* User-facing hash table type.
324
5831a5f0 325 The table stores elements of type Descriptor::value_type.
0823efed 326
5831a5f0 327 It hashes values with the hash member function.
0823efed 328 The table currently works with relatively weak hash functions.
5831a5f0 329 Use typed_pointer_hash <Value> when hashing pointers instead of objects.
0823efed 330
5831a5f0 331 It compares elements with the equal member function.
0823efed 332 Two elements with the same hash may not be equal.
5831a5f0 333 Use typed_pointer_equal <Value> when hashing pointers instead of objects.
0823efed 334
5831a5f0 335 It removes elements with the remove member function.
0823efed 336 This feature is useful for freeing memory.
5831a5f0
LC
337 Derive from typed_null_remove <Value> when not freeing objects.
338 Derive from typed_free_remove <Value> when doing a simple object free.
0823efed 339
5831a5f0 340 Specify the template Allocator to allocate and free memory.
0823efed
DN
341 The default is xcallocator.
342
343*/
5831a5f0 344template <typename Descriptor,
c203e8a7 345 template<typename Type> class Allocator= xcallocator>
0823efed
DN
346class hash_table
347{
5831a5f0
LC
348 typedef typename Descriptor::value_type value_type;
349 typedef typename Descriptor::compare_type compare_type;
0823efed 350
0823efed 351public:
c203e8a7
TS
352 hash_table (size_t);
353 ~hash_table ();
bf190e8d 354
c203e8a7
TS
355 /* Current size (in entries) of the hash table. */
356 size_t size () const { return m_size; }
0823efed 357
c203e8a7
TS
358 /* Return the current number of elements in this hash table. */
359 size_t elements () const { return m_n_elements - m_n_deleted; }
0823efed 360
c203e8a7
TS
361 /* Return the current number of elements in this hash table. */
362 size_t elements_with_deleted () const { return m_n_elements; }
0823efed 363
c203e8a7
TS
364 /* This function clears all entries in the given hash table. */
365 void empty ();
0823efed 366
c203e8a7
TS
367 /* This function clears a specified SLOT in a hash table. It is
368 useful when you've already done the lookup and don't want to do it
369 again. */
0823efed 370
c203e8a7 371 void clear_slot (value_type **);
0823efed 372
c203e8a7
TS
373 /* This function searches for a hash table entry equal to the given
374 COMPARABLE element starting with the given HASH value. It cannot
375 be used to insert or delete an element. */
376 value_type *find_with_hash (const compare_type *, hashval_t);
0823efed 377
c203e8a7
TS
378/* Like find_slot_with_hash, but compute the hash value from the element. */
379 value_type *find (const value_type *value)
380 {
381 return find_with_hash (value, Descriptor::hash (value));
382 }
0823efed 383
c203e8a7
TS
384 value_type **find_slot (const value_type *value, insert_option insert)
385 {
386 return find_slot_with_hash (value, Descriptor::hash (value), insert);
387 }
0823efed 388
c203e8a7
TS
389 /* This function searches for a hash table slot containing an entry
390 equal to the given COMPARABLE element and starting with the given
391 HASH. To delete an entry, call this with insert=NO_INSERT, then
392 call clear_slot on the slot returned (possibly after doing some
393 checks). To insert an entry, call this with insert=INSERT, then
394 write the value you want into the returned slot. When inserting an
395 entry, NULL may be returned if memory allocation fails. */
396 value_type **find_slot_with_hash (const compare_type *comparable,
397 hashval_t hash, enum insert_option insert);
0823efed 398
c203e8a7
TS
399 /* This function deletes an element with the given COMPARABLE value
400 from hash table starting with the given HASH. If there is no
401 matching element in the hash table, this function does nothing. */
402 void remove_elt_with_hash (const compare_type *, hashval_t);
0823efed 403
c203e8a7
TS
404/* Like remove_elt_with_hash, but compute the hash value from the element. */
405 void remove_elt (const value_type *value)
406 {
407 remove_elt_with_hash (value, Descriptor::hash (value));
408 }
0823efed 409
c203e8a7
TS
410 /* This function scans over the entire hash table calling CALLBACK for
411 each live entry. If CALLBACK returns false, the iteration stops.
412 ARGUMENT is passed as CALLBACK's second argument. */
413 template <typename Argument,
414 int (*Callback) (value_type **slot, Argument argument)>
415 void traverse_noresize (Argument argument);
0823efed 416
c203e8a7
TS
417 /* Like traverse_noresize, but does resize the table when it is too empty
418 to improve effectivity of subsequent calls. */
419 template <typename Argument,
420 int (*Callback) (value_type **slot, Argument argument)>
421 void traverse (Argument argument);
0823efed 422
c203e8a7
TS
423 class iterator
424 {
425 public:
426 iterator () : m_slot (NULL), m_limit (NULL) {}
0823efed 427
c203e8a7
TS
428 iterator (value_type **slot, value_type **limit) :
429 m_slot (slot), m_limit (limit) {}
0823efed 430
c203e8a7
TS
431 inline value_type &operator * () { return **m_slot; }
432 void slide ();
433 inline iterator &operator ++ ();
434 bool operator != (const iterator &other) const
435 {
436 return m_slot != other.m_slot || m_limit != other.m_limit;
437 }
0823efed 438
c203e8a7
TS
439 private:
440 value_type **m_slot;
441 value_type **m_limit;
442 };
0823efed 443
c203e8a7
TS
444 iterator begin () const
445 {
446 iterator iter (m_entries, m_entries + m_size);
447 iter.slide ();
448 return iter;
449 }
0823efed 450
c203e8a7 451 iterator end () const { return iterator (); }
0823efed 452
c203e8a7
TS
453 double collisions () const
454 {
455 return m_searches ? static_cast <double> (m_collisions) / m_searches : 0;
456 }
0823efed 457
c203e8a7 458private:
0823efed 459
c203e8a7
TS
460 value_type **find_empty_slot_for_expand (hashval_t);
461 void expand ();
bf190e8d 462
c203e8a7
TS
463 /* Table itself. */
464 typename Descriptor::value_type **m_entries;
bf190e8d 465
c203e8a7 466 size_t m_size;
bf190e8d 467
c203e8a7
TS
468 /* Current number of elements including also deleted elements. */
469 size_t m_n_elements;
0823efed 470
c203e8a7
TS
471 /* Current number of deleted elements in the table. */
472 size_t m_n_deleted;
0823efed 473
c203e8a7
TS
474 /* The following member is used for debugging. Its value is number
475 of all calls of `htab_find_slot' for the hash table. */
476 unsigned int m_searches;
0823efed 477
c203e8a7
TS
478 /* The following member is used for debugging. Its value is number
479 of collisions fixed for time of work with the hash table. */
480 unsigned int m_collisions;
0823efed 481
c203e8a7
TS
482 /* Current size (in entries) of the hash table, as an index into the
483 table of primes. */
484 unsigned int m_size_prime_index;
485};
0823efed 486
c203e8a7
TS
487template<typename Descriptor, template<typename Type> class Allocator>
488hash_table<Descriptor, Allocator>::hash_table (size_t size) :
489 m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0)
0823efed
DN
490{
491 unsigned int size_prime_index;
492
493 size_prime_index = hash_table_higher_prime_index (size);
494 size = prime_tab[size_prime_index].prime;
495
c203e8a7
TS
496 m_entries = Allocator <value_type*> ::data_alloc (size);
497 gcc_assert (m_entries != NULL);
498 m_size = size;
499 m_size_prime_index = size_prime_index;
0823efed
DN
500}
501
c203e8a7
TS
502template<typename Descriptor, template<typename Type> class Allocator>
503hash_table<Descriptor, Allocator>::~hash_table ()
0823efed 504{
c203e8a7
TS
505 for (size_t i = m_size - 1; i < m_size; i--)
506 if (m_entries[i] != HTAB_EMPTY_ENTRY && m_entries[i] != HTAB_DELETED_ENTRY)
507 Descriptor::remove (m_entries[i]);
0823efed 508
c203e8a7 509 Allocator <value_type *> ::data_free (m_entries);
0823efed
DN
510}
511
0823efed 512/* Similar to find_slot, but without several unwanted side effects:
5deac340 513 - Does not call equal when it finds an existing entry.
0823efed
DN
514 - Does not change the count of elements/searches/collisions in the
515 hash table.
516 This function also assumes there are no deleted entries in the table.
517 HASH is the hash value for the element to be inserted. */
518
c203e8a7 519template<typename Descriptor, template<typename Type> class Allocator>
5831a5f0 520typename Descriptor::value_type **
c203e8a7 521hash_table<Descriptor, Allocator>::find_empty_slot_for_expand (hashval_t hash)
0823efed 522{
c203e8a7
TS
523 hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
524 size_t size = m_size;
525 value_type **slot = m_entries + index;
0823efed
DN
526 hashval_t hash2;
527
528 if (*slot == HTAB_EMPTY_ENTRY)
529 return slot;
530 else if (*slot == HTAB_DELETED_ENTRY)
531 abort ();
532
c203e8a7 533 hash2 = hash_table_mod2 (hash, m_size_prime_index);
0823efed
DN
534 for (;;)
535 {
536 index += hash2;
537 if (index >= size)
538 index -= size;
539
c203e8a7 540 slot = m_entries + index;
0823efed
DN
541 if (*slot == HTAB_EMPTY_ENTRY)
542 return slot;
543 else if (*slot == HTAB_DELETED_ENTRY)
544 abort ();
545 }
546}
547
0823efed
DN
548/* The following function changes size of memory allocated for the
549 entries and repeatedly inserts the table elements. The occupancy
550 of the table after the call will be about 50%. Naturally the hash
551 table must already exist. Remember also that the place of the
552 table entries is changed. If memory allocation fails, this function
553 will abort. */
554
c203e8a7 555 template<typename Descriptor, template<typename Type> class Allocator>
0823efed 556void
c203e8a7 557hash_table<Descriptor, Allocator>::expand ()
0823efed 558{
c203e8a7
TS
559 value_type **oentries = m_entries;
560 unsigned int oindex = m_size_prime_index;
561 size_t osize = size ();
562 value_type **olimit = oentries + osize;
563 size_t elts = elements ();
0823efed
DN
564
565 /* Resize only when table after removal of unused elements is either
566 too full or too empty. */
c203e8a7
TS
567 unsigned int nindex;
568 size_t nsize;
0823efed
DN
569 if (elts * 2 > osize || (elts * 8 < osize && osize > 32))
570 {
571 nindex = hash_table_higher_prime_index (elts * 2);
572 nsize = prime_tab[nindex].prime;
573 }
574 else
575 {
576 nindex = oindex;
577 nsize = osize;
578 }
579
c203e8a7 580 value_type **nentries = Allocator <value_type *> ::data_alloc (nsize);
0823efed 581 gcc_assert (nentries != NULL);
c203e8a7
TS
582 m_entries = nentries;
583 m_size = nsize;
584 m_size_prime_index = nindex;
585 m_n_elements -= m_n_deleted;
586 m_n_deleted = 0;
0823efed 587
c203e8a7 588 value_type **p = oentries;
0823efed
DN
589 do
590 {
5831a5f0 591 value_type *x = *p;
0823efed
DN
592
593 if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
594 {
5831a5f0 595 value_type **q = find_empty_slot_for_expand (Descriptor::hash (x));
0823efed
DN
596
597 *q = x;
598 }
599
600 p++;
601 }
602 while (p < olimit);
603
5831a5f0 604 Allocator <value_type *> ::data_free (oentries);
0823efed
DN
605}
606
c203e8a7
TS
607template<typename Descriptor, template<typename Type> class Allocator>
608void
609hash_table<Descriptor, Allocator>::empty ()
610{
611 size_t size = m_size;
612 value_type **entries = m_entries;
613 int i;
614
615 for (i = size - 1; i >= 0; i--)
616 if (entries[i] != HTAB_EMPTY_ENTRY && entries[i] != HTAB_DELETED_ENTRY)
617 Descriptor::remove (entries[i]);
618
619 /* Instead of clearing megabyte, downsize the table. */
620 if (size > 1024*1024 / sizeof (PTR))
621 {
622 int nindex = hash_table_higher_prime_index (1024 / sizeof (PTR));
623 int nsize = prime_tab[nindex].prime;
624
625 Allocator <value_type *> ::data_free (m_entries);
626 m_entries = Allocator <value_type *> ::data_alloc (nsize);
627 m_size = nsize;
628 m_size_prime_index = nindex;
629 }
630 else
631 memset (entries, 0, size * sizeof (value_type *));
632 m_n_deleted = 0;
633 m_n_elements = 0;
634}
635
636/* This function clears a specified SLOT in a hash table. It is
637 useful when you've already done the lookup and don't want to do it
638 again. */
639
640template<typename Descriptor, template<typename Type> class Allocator>
641void
642hash_table<Descriptor, Allocator>::clear_slot (value_type **slot)
643{
644 if (slot < m_entries || slot >= m_entries + size ()
645 || *slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY)
646 abort ();
647
648 Descriptor::remove (*slot);
649
650 *slot = static_cast <value_type *> (HTAB_DELETED_ENTRY);
651 m_n_deleted++;
652}
0823efed
DN
653
654/* This function searches for a hash table entry equal to the given
655 COMPARABLE element starting with the given HASH value. It cannot
656 be used to insert or delete an element. */
657
c203e8a7 658template<typename Descriptor, template<typename Type> class Allocator>
5831a5f0 659typename Descriptor::value_type *
c203e8a7 660hash_table<Descriptor, Allocator>
5831a5f0 661::find_with_hash (const compare_type *comparable, hashval_t hash)
0823efed 662{
c203e8a7
TS
663 m_searches++;
664 size_t size = m_size;
665 hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
0823efed 666
c203e8a7 667 value_type *entry = m_entries[index];
0823efed 668 if (entry == HTAB_EMPTY_ENTRY
5831a5f0 669 || (entry != HTAB_DELETED_ENTRY && Descriptor::equal (entry, comparable)))
0823efed
DN
670 return entry;
671
c203e8a7 672 hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index);
0823efed
DN
673 for (;;)
674 {
c203e8a7 675 m_collisions++;
0823efed
DN
676 index += hash2;
677 if (index >= size)
678 index -= size;
679
c203e8a7 680 entry = m_entries[index];
0823efed 681 if (entry == HTAB_EMPTY_ENTRY
5831a5f0
LC
682 || (entry != HTAB_DELETED_ENTRY
683 && Descriptor::equal (entry, comparable)))
0823efed
DN
684 return entry;
685 }
686}
687
0823efed
DN
688/* This function searches for a hash table slot containing an entry
689 equal to the given COMPARABLE element and starting with the given
690 HASH. To delete an entry, call this with insert=NO_INSERT, then
691 call clear_slot on the slot returned (possibly after doing some
692 checks). To insert an entry, call this with insert=INSERT, then
693 write the value you want into the returned slot. When inserting an
694 entry, NULL may be returned if memory allocation fails. */
695
c203e8a7 696template<typename Descriptor, template<typename Type> class Allocator>
5831a5f0 697typename Descriptor::value_type **
c203e8a7 698hash_table<Descriptor, Allocator>
5831a5f0 699::find_slot_with_hash (const compare_type *comparable, hashval_t hash,
0823efed
DN
700 enum insert_option insert)
701{
c203e8a7
TS
702 if (insert == INSERT && m_size * 3 <= m_n_elements * 4)
703 expand ();
0823efed 704
c203e8a7 705 m_searches++;
0823efed 706
c203e8a7
TS
707 value_type **first_deleted_slot = NULL;
708 hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
709 hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index);
710 value_type *entry = m_entries[index];
711 size_t size = m_size;
0823efed
DN
712 if (entry == HTAB_EMPTY_ENTRY)
713 goto empty_entry;
714 else if (entry == HTAB_DELETED_ENTRY)
c203e8a7 715 first_deleted_slot = &m_entries[index];
5831a5f0 716 else if (Descriptor::equal (entry, comparable))
c203e8a7 717 return &m_entries[index];
5831a5f0 718
0823efed
DN
719 for (;;)
720 {
c203e8a7 721 m_collisions++;
0823efed
DN
722 index += hash2;
723 if (index >= size)
724 index -= size;
5831a5f0 725
c203e8a7 726 entry = m_entries[index];
0823efed
DN
727 if (entry == HTAB_EMPTY_ENTRY)
728 goto empty_entry;
729 else if (entry == HTAB_DELETED_ENTRY)
730 {
731 if (!first_deleted_slot)
c203e8a7 732 first_deleted_slot = &m_entries[index];
0823efed 733 }
5831a5f0 734 else if (Descriptor::equal (entry, comparable))
c203e8a7 735 return &m_entries[index];
0823efed
DN
736 }
737
738 empty_entry:
739 if (insert == NO_INSERT)
740 return NULL;
741
742 if (first_deleted_slot)
743 {
c203e8a7 744 m_n_deleted--;
5831a5f0 745 *first_deleted_slot = static_cast <value_type *> (HTAB_EMPTY_ENTRY);
0823efed
DN
746 return first_deleted_slot;
747 }
748
c203e8a7
TS
749 m_n_elements++;
750 return &m_entries[index];
0823efed
DN
751}
752
0823efed
DN
753/* This function deletes an element with the given COMPARABLE value
754 from hash table starting with the given HASH. If there is no
755 matching element in the hash table, this function does nothing. */
756
c203e8a7 757template<typename Descriptor, template<typename Type> class Allocator>
0823efed 758void
c203e8a7 759hash_table<Descriptor, Allocator>
5831a5f0 760::remove_elt_with_hash (const compare_type *comparable, hashval_t hash)
0823efed 761{
c203e8a7 762 value_type **slot = find_slot_with_hash (comparable, hash, NO_INSERT);
0823efed
DN
763 if (*slot == HTAB_EMPTY_ENTRY)
764 return;
765
5831a5f0 766 Descriptor::remove (*slot);
0823efed 767
5831a5f0 768 *slot = static_cast <value_type *> (HTAB_DELETED_ENTRY);
c203e8a7 769 m_n_deleted++;
0823efed
DN
770}
771
0823efed
DN
772/* This function scans over the entire hash table calling CALLBACK for
773 each live entry. If CALLBACK returns false, the iteration stops.
774 ARGUMENT is passed as CALLBACK's second argument. */
775
c203e8a7
TS
776template<typename Descriptor,
777 template<typename Type> class Allocator>
778template<typename Argument,
5831a5f0 779 int (*Callback) (typename Descriptor::value_type **slot, Argument argument)>
0823efed 780void
c203e8a7 781hash_table<Descriptor, Allocator>::traverse_noresize (Argument argument)
0823efed 782{
c203e8a7
TS
783 value_type **slot = m_entries;
784 value_type **limit = slot + size ();
0823efed
DN
785
786 do
787 {
5831a5f0 788 value_type *x = *slot;
0823efed
DN
789
790 if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
791 if (! Callback (slot, argument))
792 break;
793 }
794 while (++slot < limit);
795}
796
0823efed
DN
797/* Like traverse_noresize, but does resize the table when it is too empty
798 to improve effectivity of subsequent calls. */
799
5831a5f0 800template <typename Descriptor,
0823efed
DN
801 template <typename Type> class Allocator>
802template <typename Argument,
5831a5f0
LC
803 int (*Callback) (typename Descriptor::value_type **slot,
804 Argument argument)>
0823efed 805void
c203e8a7 806hash_table<Descriptor, Allocator>::traverse (Argument argument)
0823efed 807{
c203e8a7 808 size_t size = m_size;
0823efed
DN
809 if (elements () * 8 < size && size > 32)
810 expand ();
811
812 traverse_noresize <Argument, Callback> (argument);
813}
814
bf190e8d
LC
815/* Slide down the iterator slots until an active entry is found. */
816
c203e8a7 817template<typename Descriptor, template<typename Type> class Allocator>
bf190e8d 818void
c203e8a7 819hash_table<Descriptor, Allocator>::iterator::slide ()
bf190e8d 820{
65d3284b 821 for ( ; m_slot < m_limit; ++m_slot )
bf190e8d 822 {
65d3284b 823 value_type *x = *m_slot;
bf190e8d
LC
824 if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
825 return;
826 }
65d3284b
RS
827 m_slot = NULL;
828 m_limit = NULL;
bf190e8d
LC
829}
830
831/* Bump the iterator. */
832
c203e8a7
TS
833template<typename Descriptor, template<typename Type> class Allocator>
834inline typename hash_table<Descriptor, Allocator>::iterator &
835hash_table<Descriptor, Allocator>::iterator::operator ++ ()
bf190e8d 836{
65d3284b 837 ++m_slot;
bf190e8d
LC
838 slide ();
839 return *this;
840}
841
bf190e8d
LC
842
843/* Iterate through the elements of hash_table HTAB,
844 using hash_table <....>::iterator ITER,
3fadf78a 845 storing each element in RESULT, which is of type TYPE. */
bf190e8d
LC
846
847#define FOR_EACH_HASH_TABLE_ELEMENT(HTAB, RESULT, TYPE, ITER) \
848 for ((ITER) = (HTAB).begin (); \
849 (ITER) != (HTAB).end () ? (RESULT = &*(ITER) , true) : false; \
850 ++(ITER))
851
0823efed 852#endif /* TYPED_HASHTAB_H */