19#ifndef CLICK_HASHMAP_CC
20#define CLICK_HASHMAP_CC
21#include <click/hashmap.hh>
22#include <click/bighashmap_arena.hh>
23#include <click/glue.hh>
27#define BIGHASHMAP_REARRANGE_ON_FIND 0
29template <
class K,
class V>
31HashMap<K, V>::initialize(HashMap_ArenaFactory *factory,
size_t initial_nbuckets)
33 _nbuckets = initial_nbuckets;
34 _buckets = (Elt **) CLICK_LALLOC(_nbuckets *
sizeof(Elt *));
35 for (
size_t i = 0; i < _nbuckets; i++)
37 set_dynamic_resizing(
true);
44template <
class K,
class V>
45HashMap<K, V>::HashMap()
46 : _default_value(), _arena(0)
48 initialize(0, DEFAULT_INITIAL_NBUCKETS);
51template <
class K,
class V>
52HashMap<K, V>::HashMap(
const V &def, HashMap_ArenaFactory *factory)
53 : _default_value(def), _arena(0)
55 initialize(factory, DEFAULT_INITIAL_NBUCKETS);
58template <
class K,
class V>
60HashMap<K, V>::copy_from(
const HashMap<K, V> &o)
64 for (
size_t i = 0; i < _nbuckets; i++) {
65 Elt **pprev = &_buckets[i];
67 for (
const Elt *e = o._buckets[i]; e; e = e->next) {
68 Elt *ee =
reinterpret_cast<Elt *
>(_arena->alloc());
69 new(
reinterpret_cast<void *
>(&ee->key)) K(e->key);
70 new(
reinterpret_cast<void *
>(&ee->value)) V(e->value);
79template <
class K,
class V>
80HashMap<K, V>::HashMap(
const HashMap<K, V> &o)
81 : _buckets((Elt **) CLICK_LALLOC(o._nbuckets * sizeof(Elt *))),
82 _nbuckets(o._nbuckets), _default_value(o._default_value),
83 _capacity(o._capacity), _arena(o._arena)
89template <
class K,
class V>
91HashMap<K, V>::operator=(
const HashMap<K, V> &o)
95 _default_value = o._default_value;
96 if (_nbuckets < o._nbuckets)
98 _nbuckets = o._nbuckets;
99 _capacity = o._capacity;
105template <
class K,
class V>
106HashMap<K, V>::~HashMap()
108 for (
size_t i = 0; i < _nbuckets; i++)
109 for (Elt *e = _buckets[i]; e; ) {
116 CLICK_LFREE(_buckets, _nbuckets *
sizeof(Elt *));
120template <
class K,
class V>
122HashMap<K, V>::set_dynamic_resizing(
bool on)
125 _capacity = 0x7FFFFFFF;
126 else if (_nbuckets >= MAX_NBUCKETS)
127 _capacity = 0x7FFFFFFE;
129 _capacity = DEFAULT_RESIZE_THRESHOLD * _nbuckets;
132template <
class K,
class V>
134HashMap<K, V>::set_arena(HashMap_ArenaFactory *factory)
139 _arena = HashMap_ArenaFactory::get_arena(
sizeof(Elt), factory);
143template <
class K,
class V>
145HashMap<K, V>::bucket(
const K &key)
const
147 return ((
size_t) hashcode(key)) % _nbuckets;
150template <
class K,
class V>
151typename HashMap<K, V>::Pair *
152HashMap<K, V>::find_pair(
const K &key)
const
154#if BIGHASHMAP_REARRANGE_ON_FIND
156 size_t b = bucket(key);
157 for (Elt *e = _buckets[b]; e; prev = e, e = e->next)
161 prev->next = e->next;
162 e->next = _buckets[b];
169 for (Elt *e = _buckets[bucket(key)]; e; e = e->next)
177template <
class K,
class V>
179HashMap<K, V>::resize0(
size_t new_nbuckets)
181 Elt **new_buckets = (Elt **) CLICK_LALLOC(new_nbuckets *
sizeof(Elt *));
182 for (
size_t i = 0; i < new_nbuckets; i++)
185 size_t old_nbuckets = _nbuckets;
186 Elt **old_buckets = _buckets;
187 _nbuckets = new_nbuckets;
188 _buckets = new_buckets;
189 if (dynamic_resizing())
190 set_dynamic_resizing(
true);
192 for (
size_t i = 0; i < old_nbuckets; i++)
193 for (Elt *e = old_buckets[i]; e; ) {
195 size_t b = bucket(e->key);
196 e->next = new_buckets[b];
201 CLICK_LFREE(old_buckets, old_nbuckets *
sizeof(Elt *));
204template <
class K,
class V>
206HashMap<K, V>::resize(
size_t want_nbuckets)
208 size_t new_nbuckets = 1;
209 while (new_nbuckets < want_nbuckets && new_nbuckets < MAX_NBUCKETS)
210 new_nbuckets = ((new_nbuckets + 1) << 1) - 1;
211 assert(new_nbuckets > 0 && new_nbuckets <= MAX_NBUCKETS);
212 if (_nbuckets != new_nbuckets)
213 resize0(new_nbuckets);
216template <
class K,
class V>
218HashMap<K, V>::insert(
const K &key,
const V &value)
220 size_t b = bucket(key);
221 for (Elt *e = _buckets[b]; e; e = e->next)
227 if (_n >= _capacity) {
228 resize(_nbuckets + 1);
232 if (Elt *e =
reinterpret_cast<Elt *
>(_arena->alloc())) {
233 new(
reinterpret_cast<void *
>(&e->key)) K(key);
234 new(
reinterpret_cast<void *
>(&e->value)) V(value);
235 e->next = _buckets[b];
242template <
class K,
class V>
244HashMap<K, V>::erase(
const K &key)
246 size_t b = bucket(key);
248 Elt *e = _buckets[b];
249 while (e && !(e->key == key)) {
255 prev->next = e->next;
257 _buckets[b] = e->next;
267template <
class K,
class V>
268typename HashMap<K, V>::Pair *
269HashMap<K, V>::find_pair_force(
const K &key,
const V &default_value)
271 size_t b = bucket(key);
272 for (Elt *e = _buckets[b]; e; e = e->next)
275 if (_n >= _capacity) {
276 resize(_nbuckets + 1);
279 if (Elt *e =
reinterpret_cast<Elt *
>(_arena->alloc())) {
280 new(
reinterpret_cast<void *
>(&e->key)) K(key);
281 new(
reinterpret_cast<void *
>(&e->value)) V(default_value);
282 e->next = _buckets[b];
290template <
class K,
class V>
292HashMap<K, V>::clear()
294 for (
size_t i = 0; i < _nbuckets; i++) {
295 for (Elt *e = _buckets[i]; e; ) {
307template <
class K,
class V>
309HashMap<K, V>::swap(HashMap<K, V> &o)
314 HashMap_Arena *t_arena;
316 t_elts = _buckets; _buckets = o._buckets; o._buckets = t_elts;
317 t_size = _nbuckets; _nbuckets = o._nbuckets; o._nbuckets = t_size;
318 t_v = _default_value; _default_value = o._default_value; o._default_value = t_v;
320 t_size = _n; _n = o._n; o._n = t_size;
321 t_size = _capacity; _capacity = o._capacity; o._capacity = t_size;
323 t_arena = _arena; _arena = o._arena; o._arena = t_arena;
326template <
class K,
class V>
327_HashMap_const_iterator<K, V>::_HashMap_const_iterator(
const HashMap<K, V> *hm,
bool begin)
330 size_t nb = _hm->_nbuckets;
331 typename HashMap<K, V>::Elt **b = _hm->_buckets;
332 for (_bucket = 0; _bucket < nb && begin; _bucket++)
340template <
class K,
class V>
342_HashMap_const_iterator<K, V>::operator++(
int)
347 size_t nb = _hm->_nbuckets;
348 typename HashMap<K, V>::Elt **b = _hm->_buckets;
349 for (_bucket++; _bucket < nb; _bucket++)
360HashMap_partition_elts(
void **elts,
size_t left,
size_t right)
362 void *pivot = elts[(left + right) / 2];
367 while (left < right) {
368 if (elts[left] < pivot)
370 else if (elts[right] > pivot)
373 void *x = elts[left];
374 elts[left] = elts[right];
383HashMap_qsort_elts(
void **elts,
size_t left,
size_t right)
386 size_t split = HashMap_partition_elts(elts, left, right);
387 HashMap_qsort_elts(elts, left, split);
388 HashMap_qsort_elts(elts, split, right);
398HashMap<K, void *>::initialize(HashMap_ArenaFactory *factory,
size_t initial_nbuckets)
400 _nbuckets = initial_nbuckets;
401 _buckets = (Elt **) CLICK_LALLOC(_nbuckets *
sizeof(Elt *));
402 for (
size_t i = 0; i < _nbuckets; i++)
404 set_dynamic_resizing(
true);
412HashMap<K, void *>::HashMap()
413 : _default_value(0), _arena(0)
415 initialize(0, DEFAULT_INITIAL_NBUCKETS);
419HashMap<K, void *>::HashMap(
void *def, HashMap_ArenaFactory *factory)
420 : _default_value(def), _arena(0)
422 initialize(factory, DEFAULT_INITIAL_NBUCKETS);
427HashMap<K, void *>::copy_from(
const HashMap<K, void *> &o)
429 for (
size_t i = 0; i < _nbuckets; i++) {
430 Elt **pprev = &_buckets[i];
432 for (
const Elt *e = o._buckets[i]; e; e = e->next) {
433 Elt *ee =
reinterpret_cast<Elt *
>(_arena->alloc());
434 new(
reinterpret_cast<void *
>(&ee->key)) K(e->key);
435 ee->value = e->value;
445HashMap<K, void *>::HashMap(
const HashMap<K, void *> &o)
446 : _buckets((Elt **) CLICK_LALLOC(o._nbuckets * sizeof(Elt *))),
447 _nbuckets(o._nbuckets), _default_value(o._default_value),
448 _capacity(o._capacity), _arena(o._arena)
456HashMap<K, void *>::operator=(
const HashMap<K, void *> &o)
460 _default_value = o._default_value;
461 if (_nbuckets < o._nbuckets)
462 resize0(o._nbuckets);
463 _nbuckets = o._nbuckets;
464 _capacity = o._capacity;
471HashMap<K, void *>::~HashMap()
473 for (
size_t i = 0; i < _nbuckets; i++)
474 for (Elt *e = _buckets[i]; e; ) {
480 CLICK_LFREE(_buckets, _nbuckets *
sizeof(Elt *));
486HashMap<K, void *>::set_dynamic_resizing(
bool on)
489 _capacity = 0x7FFFFFFF;
490 else if (_nbuckets >= MAX_NBUCKETS)
491 _capacity = 0x7FFFFFFE;
493 _capacity = DEFAULT_RESIZE_THRESHOLD * _nbuckets;
498HashMap<K, void *>::set_arena(HashMap_ArenaFactory *factory)
503 _arena = HashMap_ArenaFactory::get_arena(
sizeof(Elt), factory);
509HashMap<K, void *>::bucket(
const K &key)
const
511 return ((
size_t) hashcode(key)) % _nbuckets;
515typename HashMap<K, void *>::Pair *
516HashMap<K, void *>::find_pair(
const K &key)
const
518#if BIGHASHMAP_REARRANGE_ON_FIND
520 size_t b = bucket(key);
521 for (Elt *e = _buckets[b]; e; prev = e, e = e->next)
525 prev->next = e->next;
526 e->next = _buckets[b];
533 for (Elt *e = _buckets[bucket(key)]; e; e = e->next)
543HashMap<K, void *>::resize0(
size_t new_nbuckets)
545 Elt **new_buckets = (Elt **) CLICK_LALLOC(new_nbuckets *
sizeof(Elt *));
546 for (
size_t i = 0; i < new_nbuckets; i++)
549 size_t old_nbuckets = _nbuckets;
550 Elt **old_buckets = _buckets;
551 _nbuckets = new_nbuckets;
552 _buckets = new_buckets;
553 if (dynamic_resizing())
554 set_dynamic_resizing(
true);
556 for (
size_t i = 0; i < old_nbuckets; i++)
557 for (Elt *e = old_buckets[i]; e; ) {
559 size_t b = bucket(e->key);
560 e->next = new_buckets[b];
565 CLICK_LFREE(old_buckets, old_nbuckets *
sizeof(Elt *));
570HashMap<K, void *>::resize(
size_t want_nbuckets)
572 size_t new_nbuckets = 1;
573 while (new_nbuckets < want_nbuckets && new_nbuckets < MAX_NBUCKETS)
574 new_nbuckets = ((new_nbuckets + 1) << 1) - 1;
575 assert(new_nbuckets > 0 && new_nbuckets <= MAX_NBUCKETS);
576 if (_nbuckets != new_nbuckets)
577 resize0(new_nbuckets);
582HashMap<K, void *>::insert(
const K &key,
void *value)
584 size_t b = bucket(key);
585 for (Elt *e = _buckets[b]; e; e = e->next)
591 if (_n >= _capacity) {
592 resize(_nbuckets + 1);
596 if (Elt *e =
reinterpret_cast<Elt *
>(_arena->alloc())) {
597 new(
reinterpret_cast<void *
>(&e->key)) K(key);
599 e->next = _buckets[b];
608HashMap<K, void *>::erase(
const K &key)
610 size_t b = bucket(key);
612 Elt *e = _buckets[b];
613 while (e && !(e->key == key)) {
619 prev->next = e->next;
621 _buckets[b] = e->next;
631typename HashMap<K, void *>::Pair *
632HashMap<K, void *>::find_pair_force(
const K &key,
void *default_value)
634 size_t b = bucket(key);
635 for (Elt *e = _buckets[b]; e; e = e->next)
638 if (_n >= _capacity) {
639 resize(_nbuckets + 1);
642 if (Elt *e =
reinterpret_cast<Elt *
>(_arena->alloc())) {
643 new(
reinterpret_cast<void *
>(&e->key)) K(key);
644 e->value = default_value;
645 e->next = _buckets[b];
655HashMap<K, void *>::clear()
657 for (
size_t i = 0; i < _nbuckets; i++) {
658 for (Elt *e = _buckets[i]; e; ) {
671HashMap<K, void *>::swap(HashMap<K, void *> &o)
676 HashMap_Arena *t_arena;
678 t_elts = _buckets; _buckets = o._buckets; o._buckets = t_elts;
679 t_size = _nbuckets; _nbuckets = o._nbuckets; o._nbuckets = t_size;
680 t_v = _default_value; _default_value = o._default_value; o._default_value = t_v;
682 t_size = _n; _n = o._n; o._n = t_size;
683 t_size = _capacity; _capacity = o._capacity; o._capacity = t_size;
685 t_arena = _arena; _arena = o._arena; o._arena = t_arena;
690_HashMap_const_iterator<K, void *>::_HashMap_const_iterator(
const HashMap<K, void *> *hm,
bool begin)
693 size_t nb = _hm->_nbuckets;
694 typename HashMap<K, void *>::Elt **b = _hm->_buckets;
695 for (_bucket = 0; _bucket < nb && begin; _bucket++)
705_HashMap_const_iterator<K, void *>::operator++(
int)
710 size_t nb = _hm->_nbuckets;
711 typename HashMap<K, void *>::Elt **b = _hm->_buckets;
712 for (_bucket++; _bucket < nb; _bucket++)