1 // Hash sets (hash tables with 1 key and no value)
7 #include "cl_iterator.h"
12 // - function bool equal (key1_type,key1_type);
13 // - function unsigned long hashcode (key1_type);
15 template <class key1_type>
16 struct cl_htsetentry {
17 ALLOCATE_ANYWHERE(cl_htsetentry)
19 cl_htsetentry (const key1_type& k)
23 template <class key1_type>
24 struct cl_heap_hashtable_set : public cl_heap_hashtable <cl_htsetentry <key1_type> > {
27 typedef typename cl_heap_hashtable <cl_htsetentry <key1_type> >::htxentry htxentry;
30 void* operator new (size_t size) { return malloc_hook(size); }
32 void operator delete (void* ptr) { free_hook(ptr); }
34 // Lookup (htref alias gethash).
35 bool get (const key1_type& key)
37 var long index = _slots[hashcode(key) % _modulus] - 1;
41 if (equal(key,_entries[index].entry.key))
43 index = _entries[index].next - 1;
47 // Store (htset alias puthash).
48 void put (const key1_type& key)
50 var unsigned long hcode = hashcode(key);
51 // Search whether it is already there.
53 var long index = _slots[hcode % _modulus] - 1;
57 if (equal(key,_entries[index].entry.key))
59 index = _entries[index].next - 1;
62 // Put it into the table.
64 var long hindex = hcode % _modulus; // _modulus may have changed!
65 var long index = get_free_index();
66 new (&_entries[index].entry) cl_htsetentry<key1_type> (key);
67 _entries[index].next = _slots[hindex];
68 _slots[hindex] = 1+index;
71 // Remove (htrem alias remhash).
72 void remove (const key1_type& key)
74 var long* _index = &_slots[hashcode(key) % _modulus];
76 var long index = *_index - 1;
79 if (equal(key,_entries[index].entry.key)) {
80 // Remove _entries[index].entry
81 *_index = _entries[index].next;
82 _entries[index].~htxentry();
83 // The entry is now free.
84 put_free_index(index);
89 _index = &_entries[index].next;
92 // Iterate through the table.
93 // No stuff should be inserted into the table during the iteration,
94 // or you may find yourself iterating over an entry vector which has
95 // already been freed!
98 // Prepare a store operation: make sure that the free list is non-empty.
99 // This may change the table's size!
100 void prepare_store ()
102 #if !(defined(__sparc__) && !defined(__GNUC__))
106 if (_garcol_fun(this))
109 // No! Have to grow the hash table.
112 // workaround Sun C++ 4.1 inline function compiler bug
113 if (_freelist >= -1) {
114 if (!_garcol_fun(this) || (_freelist >= -1))
121 var long new_size = _size + (_size >> 1) + 1; // _size*1.5
122 var long new_modulus = compute_modulus(new_size);
123 var void* new_total_vector = malloc_hook(new_modulus*sizeof(long) + new_size*sizeof(htxentry));
124 var long* new_slots = (long*) ((char*)new_total_vector + 0);
125 var htxentry* new_entries = (htxentry *) ((char*)new_total_vector + new_modulus*sizeof(long));
126 for (var long hi = new_modulus-1; hi >= 0; hi--)
128 var long free_list_head = -1;
129 for (var long i = new_size-1; i >= 0; i--) {
130 new_entries[i].next = free_list_head;
131 free_list_head = -2-i;
133 var htxentry* old_entries = _entries;
134 for (var long old_index = 0; old_index < _size; old_index++)
135 if (old_entries[old_index].next >= 0) {
136 var key1_type& key = old_entries[old_index].entry.key;
137 var long hindex = hashcode(key) % new_modulus;
138 var long index = -2-free_list_head;
139 free_list_head = new_entries[index].next;
140 new (&new_entries[index].entry) cl_htsetentry<key1_type> (key);
141 new_entries[index].next = new_slots[hindex];
142 new_slots[hindex] = 1+index;
143 old_entries[old_index].~htxentry();
145 free_hook(_total_vector);
146 _modulus = new_modulus;
148 _freelist = free_list_head;
150 _entries = new_entries;
151 _total_vector = new_total_vector;
157 #endif /* _CL_HASHSET_H */