Click
Loading...
Searching...
No Matches
hashtable.hh
Go to the documentation of this file.
1#ifndef CLICK_HASHTABLE_HH
2#define CLICK_HASHTABLE_HH
3/*
4 * hashtable.hh -- HashTable template
5 * Eddie Kohler
6 *
7 * Copyright (c) 2008 Meraki, Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software")
11 * to deal in the Software without restriction, subject to the conditions
12 * listed in the Click LICENSE file. These conditions include: you must
13 * preserve this copyright notice, and you cannot mention the copyright
14 * holders in advertising related to the Software without their permission.
15 * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
16 * notice is a summary of the Click LICENSE file; the license in that file is
17 * legally binding.
18 */
19#include <click/pair.hh>
20#include <click/hashcontainer.hh>
21#include <click/hashallocator.hh>
22CLICK_DECLS
23
28template <typename K, typename V = void> class HashTable;
29template <typename T> class HashTable_iterator;
30template <typename T> class HashTable_const_iterator;
31
98template <typename T>
99class HashTable<T> {
100
101 struct elt {
102 T v;
103 elt *_hashnext;
104 elt(const T &v_)
105 : v(v_) {
106 }
107 typedef typename T::key_type key_type;
108 typedef typename T::key_const_reference key_const_reference;
109 key_const_reference hashkey() const {
110 return v.hashkey();
111 }
112 };
113
114 typedef HashContainer<elt> rep_type;
115
116 public:
117
119 typedef typename T::key_type key_type;
120
122 typedef typename T::key_const_reference key_const_reference;
123
125 typedef T value_type;
126
128 typedef typename rep_type::size_type size_type;
129
131 typedef typename rep_type::bucket_count_type bucket_count_type;
132
133
135 HashTable()
136 : _rep() {
137 }
138
143 explicit HashTable(bucket_count_type n)
144 : _rep(n) {
145 }
146
148 HashTable(const HashTable<T> &x)
149 : _rep(x._rep.bucket_count()) {
150 clone_elements(x);
151 }
152
153#if HAVE_CXX_RVALUE_REFERENCES
156 : _rep() {
157 x.swap(*this);
158 }
159#endif
160
162 ~HashTable();
163
164
166 inline size_type size() const {
167 return _rep.size();
168 }
169
171 inline bool empty() const {
172 return _rep.empty();
173 }
174
176 inline bucket_count_type bucket_count() const {
177 return _rep.bucket_count();
178 }
179
182 inline size_type bucket_size(bucket_count_type n) const {
183 return _rep.bucket_size(n);
184 }
185
186
187 typedef HashTable_const_iterator<T> const_iterator;
188 typedef HashTable_iterator<T> iterator;
189
193 inline iterator begin();
195 inline const_iterator begin() const;
196
199 inline iterator end();
201 inline const_iterator end() const;
202
203
205 inline size_type count(key_const_reference key) const;
206
210 inline iterator find(key_const_reference key);
212 inline const_iterator find(key_const_reference key) const;
213
221 inline iterator find_prefer(key_const_reference key);
222
234 inline iterator find_insert(key_const_reference key);
235
247
257 inline iterator find_insert(const value_type &value);
258
268 bool set(const value_type &value);
269
273 iterator erase(const iterator &it);
274
278 size_type erase(const key_type &key);
279
282 void clear();
283
284
286 void swap(HashTable<T> &x);
287
288
293 void rehash(bucket_count_type n) {
294 _rep.rehash(n);
295 }
296
297
300
301#if HAVE_CXX_RVALUE_REFERENCES
303 inline HashTable<T> &operator=(HashTable<T> &&x) {
304 x.swap(*this);
305 return *this;
306 }
307#endif
308
309 private:
310
311 rep_type _rep;
312 SizedHashAllocator<sizeof(elt)> _alloc;
313
314 void clone_elements(const HashTable<T> &);
315 void copy_elements(const HashTable<T> &);
316
317 friend class HashTable_iterator<T>;
318 friend class HashTable_const_iterator<T>;
319 template <typename K, typename V> friend class HashTable;
320
321};
322
325template <typename T>
327
331
333 const T *get() const {
334 if (_rep)
335 return &_rep.get()->v;
336 else
337 return 0;
338 }
339
342 const T *operator->() const {
343 return &_rep.get()->v;
344 }
345
348 const T &operator*() const {
349 return _rep.get()->v;
350 }
351
355 return _rep.get()->hashkey();
356 }
357
359 bool live() const {
360 return (bool) _rep;
361 }
362
363 typedef bool (HashTable_const_iterator::*unspecified_bool_type)() const;
365 inline operator unspecified_bool_type() const {
366 return _rep ? &HashTable_const_iterator::live : 0;
367 }
368
370 void operator++(int) {
371 _rep++;
372 }
373
375 void operator++() {
376 ++_rep;
377 }
378
379 private:
380
382
384 : _rep(i) {
385 }
386
387 friend class HashTable<T>;
388 friend class HashTable_iterator<T>;
389
390};
391
411template <typename T>
413
415
419
421 T *get() const {
422 return const_cast<T *>(inherited::get());
423 }
424
427 inline T *operator->() const {
428 return const_cast<T *>(inherited::operator->());
429 }
430
433 inline T &operator*() const {
434 return const_cast<T &>(inherited::operator*());
435 }
436
437 private:
438
440 : inherited(i) {
441 }
442
443 friend class HashTable<T>;
444
445};
446
449template <typename K, typename V>
450class HashTable_const_iterator<Pair<K, V> > { public:
451
454 }
455
457 const Pair<K, V> *get() const {
458 if (_rep)
459 return &_rep.get()->v;
460 else
461 return 0;
462 }
463
466 const Pair<K, V> *operator->() const {
467 return &_rep.get()->v;
468 }
469
472 const Pair<K, V> &operator*() const {
473 return _rep.get()->v;
474 }
475
479 const K &key() const {
480 return operator*().first;
481 }
482
486 const V &value() const {
487 return operator*().second;
488 }
489
491 bool live() const {
492 return (bool) _rep;
493 }
494
495 typedef bool (HashTable_const_iterator::*unspecified_bool_type)() const;
497 inline operator unspecified_bool_type() const {
498 return _rep ? &HashTable_const_iterator::live : 0;
499 }
500
502 void operator++(int) {
503 _rep++;
504 }
505
507 void operator++() {
508 ++_rep;
509 }
510
511 private:
512
513 typename HashTable<Pair<K, V> >::rep_type::const_iterator _rep;
514
515 inline HashTable_const_iterator(const typename HashTable<Pair<K, V> >::rep_type::const_iterator &i)
516 : _rep(i) {
517 }
518
519 friend class HashTable<Pair<K, V> >;
520 friend class HashTable_iterator<Pair<K, V> >;
521
522};
523
526template <typename K, typename V>
527class HashTable_iterator<Pair<K, V> > : public HashTable_const_iterator<Pair<K, V> > { public:
528
529 typedef HashTable_const_iterator<Pair<K, V> > inherited;
530
533 }
534
536 Pair<K, V> *get() const {
537 return const_cast<Pair<K, V> *>(inherited::get());
538 }
539
541 inline Pair<K, V> *operator->() const {
542 return const_cast<Pair<K, V> *>(inherited::operator->());
543 }
544
547 inline Pair<K, V> &operator*() const {
548 return const_cast<Pair<K, V> &>(inherited::operator*());
549 }
550
554 V &value() const {
555 return operator*().second;
556 }
557
558 private:
559
560 inline HashTable_iterator(const typename HashTable<Pair<K, V> >::rep_type::const_iterator &i)
561 : inherited(i) {
562 }
563
564 friend class HashTable<Pair<K, V> >;
565
566};
567
568
569template <typename K, typename V>
571
572 typedef HashTable<Pair<const K, V> > rep_type;
573
574 public:
575
577 typedef K key_type;
578
580 typedef const K &key_const_reference;
581
583 typedef V mapped_type;
584
586 typedef Pair<const K, V> value_type;
587
589 typedef typename rep_type::size_type size_type;
590
592 typedef typename rep_type::bucket_count_type bucket_count_type;
593
594
597 : _rep(), _default_value() {
598 }
599
601 explicit HashTable(const mapped_type &d)
602 : _rep(), _default_value(d) {
603 }
604
609 : _rep(n), _default_value(d) {
610 }
611
614 : _rep(x._rep), _default_value(x._default_value) {
615 }
616
617#if HAVE_CXX_RVALUE_REFERENCES
620 : _rep(), _default_value() {
621 x.swap(*this);
622 }
623#endif
624
627 }
628
629
631 inline size_type size() const {
632 return _rep.size();
633 }
634
636 inline bool empty() const {
637 return _rep.empty();
638 }
639
642 return _rep.bucket_count();
643 }
644
648 return _rep.bucket_size(n);
649 }
650
655 inline const mapped_type &default_value() const {
656 return _default_value;
657 }
658
659
660 typedef HashTable_const_iterator<value_type> const_iterator;
661 typedef HashTable_iterator<value_type> iterator;
662
666 inline iterator begin() {
667 return _rep.begin();
668 }
670 inline const_iterator begin() const {
671 return _rep.begin();
672 }
673
676 inline iterator end() {
677 return _rep.end();
678 }
680 inline const_iterator end() const {
681 return _rep.end();
682 }
683
684
687 return _rep.count(key);
688 }
689
693 inline const_iterator find(key_const_reference key) const {
694 return _rep.find(key);
695 }
697 inline iterator find(key_const_reference key) {
698 return _rep.find(key);
699 }
700
705 inline iterator find_prefer(key_const_reference key) {
706 return _rep.find_prefer(key);
707 }
708
709
715 if (const_iterator i = find(key))
716 return i.value();
717 else
718 return _default_value;
719 }
720
726 if (iterator i = find(key))
727 return &i.value();
728 else
729 return 0;
730 }
733 if (const_iterator i = find(key))
734 return &i.value();
735 else
736 return 0;
737 }
738
748 if (const_iterator i = find(key))
749 return i.value();
750 else
751 return _default_value;
752 }
753
762#if CLICK_HASHMAP_UPGRADE_WARNINGS
763 inline mapped_type &operator[](key_const_reference key) CLICK_DEPRECATED;
764#else
766#endif
767
768
778 inline iterator find_insert(key_const_reference key) {
779 return _rep.find_insert(value_type(key, _default_value));
780 }
781
791 inline iterator find_insert(key_const_reference key,
792 const mapped_type &value) {
793 return _rep.find_insert(value_type(key, value));
794 }
795
796
810 bool set(key_const_reference key, const mapped_type &value);
811
817 bool replace(key_const_reference key, const mapped_type &value) CLICK_DEPRECATED;
818
822 iterator erase(const iterator &it) {
823 return _rep.erase(it);
824 }
825
830 return _rep.erase(key);
831 }
832
835 void clear() {
836 _rep.clear();
837 }
838
839
842 _rep.swap(x._rep);
843 click_swap(x._default_value, _default_value);
844 }
845
846
852 _rep.rehash(nb);
853 }
854
855
858 _rep = x._rep;
859 _default_value = x._default_value;
860 return *this;
861 }
862
863#if HAVE_CXX_RVALUE_REFERENCES
866 x.swap(*this);
867 return *this;
868 }
869#endif
870
871 private:
872
873 rep_type _rep;
874 V _default_value;
875
876};
877
878
879
880template <typename T>
882{
883 for (typename rep_type::iterator it = _rep.begin(); it; ) {
884 elt *e = _rep.erase(it);
885 e->v.~T();
886 _alloc.deallocate(e);
887 }
888}
889
890template <typename T>
891inline typename HashTable<T>::const_iterator HashTable<T>::begin() const
892{
893 return const_iterator(_rep.begin());
894}
895
896template <typename T>
897inline typename HashTable<T>::iterator HashTable<T>::begin()
898{
899 return iterator(_rep.begin());
900}
901
902template <typename T>
903inline typename HashTable<T>::const_iterator HashTable<T>::end() const
904{
905 return const_iterator(_rep.end());
906}
907
908template <typename T>
909inline typename HashTable<T>::iterator HashTable<T>::end()
910{
911 return iterator(_rep.end());
912}
913
914template <typename T>
915inline typename HashTable<T>::size_type HashTable<T>::count(key_const_reference key) const
916{
917 return _rep.contains(key);
918}
919
920template <typename T>
921inline HashTable_const_iterator<T> HashTable<T>::find(key_const_reference key) const
922{
923 return HashTable_const_iterator<T>(_rep.find(key));
924}
925
926template <typename T>
927inline HashTable_iterator<T> HashTable<T>::find(key_const_reference key)
928{
929 return HashTable_iterator<T>(_rep.find(key));
930}
931
932template <typename T>
933inline HashTable_iterator<T> HashTable<T>::find_prefer(key_const_reference key)
934{
935 return HashTable_iterator<T>(_rep.find_prefer(key));
936}
937
938template <typename T>
940{
941 typename rep_type::iterator i = _rep.find(key);
942 if (!i)
943 if (elt *e = reinterpret_cast<elt *>(_alloc.allocate())) {
944 new(reinterpret_cast<void *>(&e->v)) T(key);
945 _rep.set(i, e, true);
946 }
947 return i;
948}
949
950template <typename T>
952HashTable<T>::operator[](key_const_reference key)
953{
954 return *find_insert(key);
955}
956
957template <typename T>
959{
960 typename rep_type::iterator i = _rep.find(hashkey(v));
961 if (!i)
962 if (elt *e = reinterpret_cast<elt *>(_alloc.allocate())) {
963 new(reinterpret_cast<void *>(&e->v)) T(v);
964 _rep.set(i, e, true);
965 }
966 return i;
967}
968
969template <typename T>
970bool HashTable<T>::set(const value_type &value)
971{
972 typename rep_type::iterator i = _rep.find(hashkey(value));
973 if (i)
974 i->v = value;
975 else if (elt *e = reinterpret_cast<elt *>(_alloc.allocate())) {
976 new(reinterpret_cast<void *>(&e->v)) T(value);
977 _rep.set(i, e, true);
978 return true;
979 }
980 return false;
981}
982
983template <typename K, typename V>
984bool HashTable<K, V>::set(const key_type &key, const mapped_type &value)
985{
986 typename rep_type::rep_type::iterator i = _rep._rep.find(key);
987 if (i)
988 i->v.second = value;
989 else if (typename rep_type::elt *e = reinterpret_cast<typename rep_type::elt *>(_rep._alloc.allocate())) {
990 new(reinterpret_cast<void *>(&e->v)) value_type(key, value);
991 _rep._rep.set(i, e, true);
992 return true;
993 }
994 return false;
995}
996
997template <typename T>
998typename HashTable<T>::iterator HashTable<T>::erase(const iterator &it)
999{
1000 iterator itx(it);
1001 if (elt *e = _rep.erase(reinterpret_cast<typename rep_type::iterator &>(itx._rep))) {
1002 e->v.~T();
1003 _alloc.deallocate(e);
1004 }
1005 return itx;
1006}
1007
1008template <typename T>
1009typename HashTable<T>::size_type HashTable<T>::erase(const key_type &key)
1010{
1011 if (elt *e = _rep.erase(key)) {
1012 e->v.~T();
1013 _alloc.deallocate(e);
1014 return 1;
1015 } else
1016 return 0;
1017}
1018
1019template <typename T>
1021 // requires that 'this' is empty and has the same number of buckets as 'o'
1022{
1023 bucket_count_type b = (bucket_count_type) -1;
1024 typename rep_type::iterator j = _rep.end();
1025 for (typename rep_type::const_iterator i = o._rep.begin(); i; ++i) {
1026 if (b != i.bucket())
1027 j = _rep.begin((b = i.bucket()));
1028 if (elt *e = reinterpret_cast<elt *>(_alloc.allocate())) {
1029 new(reinterpret_cast<void *>(&e->v)) T(i->v);
1030 _rep.insert_at(j, e);
1031 }
1032 }
1033}
1034
1035template <typename T>
1037{
1038 for (typename rep_type::const_iterator i = o._rep.begin(); i; ++i)
1039 find_insert(i->v);
1040}
1041
1042template <typename T>
1044{
1045 if (&o != this) {
1046 clear();
1047 if (_rep.bucket_count() < o._rep.bucket_count())
1048 _rep.rehash(o._rep.bucket_count());
1049 copy_elements(o);
1050 }
1051 return *this;
1052}
1053
1054template <typename T>
1056{
1057 for (typename rep_type::iterator it = _rep.begin(); it; ) {
1058 elt *e = _rep.erase(it);
1059 e->v.~T();
1060 _alloc.deallocate(e);
1061 }
1062}
1063
1064template <typename T>
1066{
1067 _rep.swap(o._rep);
1068 _alloc.swap(o._alloc);
1069}
1070
1071template <typename K, typename V>
1073{
1074 return find_insert(key).value();
1075}
1076
1077template <typename K, typename V>
1078bool HashTable<K, V>::replace(const key_type &key, const mapped_type &value)
1079{
1080 return set(key, value);
1081}
1082
1083
1085template <typename T>
1087{
1088 return a.get() == b.get();
1089}
1090
1092template <typename T>
1094{
1095 return a.get() != b.get();
1096}
1097
1098
1099template <typename K, typename V>
1100inline void click_swap(HashTable<K, V> &a, HashTable<K, V> &b)
1101{
1102 a.swap(b);
1103}
1104
1105template <typename K, typename V>
1106inline void assign_consume(HashTable<K, V> &a, HashTable<K, V> &b)
1107{
1108 a.swap(b);
1109}
1110
1111template <typename K, typename V>
1112inline void clear_by_swap(HashTable<K, V> &x)
1113{
1114 // specialization avoids losing x's default value
1116 x.swap(tmp);
1117}
1118
1119CLICK_ENDDECLS
1120#endif
Intrusive hash table template.
Definition hashcontainer.hh:85
The const_iterator type for HashTable.
Definition hashtable.hh:326
void operator++()
Advance this iterator to the next element.
Definition hashtable.hh:375
const T & operator*() const
Return a reference to the element.
Definition hashtable.hh:348
HashTable_const_iterator()
Construct an uninitialized iterator.
Definition hashtable.hh:329
const T * get() const
Return a pointer to the element, null if *this == end().
Definition hashtable.hh:333
HashTable< T >::key_const_reference key() const
Return this element's key.
Definition hashtable.hh:354
bool live() const
Return true iff *this != end().
Definition hashtable.hh:359
void operator++(int)
Advance this iterator to the next element.
Definition hashtable.hh:370
const T * operator->() const
Return a pointer to the element.
Definition hashtable.hh:342
The iterator type for HashTable.
Definition hashtable.hh:412
T & operator*() const
Return a reference to the element.
Definition hashtable.hh:433
HashTable_iterator()
Construct an uninitialized iterator.
Definition hashtable.hh:417
T * operator->() const
Return a pointer to the element.
Definition hashtable.hh:427
T * get() const
Return a pointer to the element, null if *this == end().
Definition hashtable.hh:421
Hash table template.
Definition hashtable.hh:570
const mapped_type & operator[](key_const_reference key) const
Return the value for key.
Definition hashtable.hh:747
Pair< const K, V > value_type
Pair of key type and value type.
Definition hashtable.hh:586
bool set(key_const_reference key, const mapped_type &value)
Set the mapping for key to value.
Definition hashtable.hh:984
void clear()
Remove all elements.
Definition hashtable.hh:835
void rehash(bucket_count_type nb)
Rehash the table, ensuring it contains at least n buckets.
Definition hashtable.hh:851
~HashTable()
Destroy this hash table, freeing its memory.
Definition hashtable.hh:626
size_type erase(key_const_reference key)
Remove any element with key.
Definition hashtable.hh:829
iterator erase(const iterator &it)
Remove the element indicated by it.
Definition hashtable.hh:822
HashTable< K, V > & operator=(const HashTable< K, V > &x)
Assign this hash table's contents to a copy of x.
Definition hashtable.hh:857
K key_type
Key type.
Definition hashtable.hh:577
HashTable(const HashTable< K, V > &x)
Construct a hash table as a copy of x.
Definition hashtable.hh:613
HashTable(const mapped_type &d)
Construct an empty hash table with default value d.
Definition hashtable.hh:601
size_type size() const
Return the number of elements in the hash table.
Definition hashtable.hh:631
bucket_count_type bucket_count() const
Return the number of buckets in the hash table.
Definition hashtable.hh:641
const mapped_type * get_pointer(key_const_reference key) const
Definition hashtable.hh:732
size_type count(key_const_reference key) const
Return 1 if an element with key key exists, 0 otherwise.
Definition hashtable.hh:686
mapped_type * get_pointer(key_const_reference key)
Return a pointer to the value for key.
Definition hashtable.hh:725
const mapped_type & get(key_const_reference key) const
Return the value for key.
Definition hashtable.hh:714
rep_type::bucket_count_type bucket_count_type
Type of bucket sizes.
Definition hashtable.hh:592
iterator find_insert(key_const_reference key)
Ensure an element with key key and return its iterator.
Definition hashtable.hh:778
iterator find_prefer(key_const_reference key)
Return an iterator for the element with key key, if any.
Definition hashtable.hh:705
HashTable(const mapped_type &d, bucket_count_type n)
Construct an empty hash table with at least n buckets.
Definition hashtable.hh:608
rep_type::size_type size_type
Type of sizes.
Definition hashtable.hh:589
bool empty() const
Return true iff size() == 0.
Definition hashtable.hh:636
const_iterator begin() const
Definition hashtable.hh:670
bool replace(key_const_reference key, const mapped_type &value)
Set the mapping for key to value.
Definition hashtable.hh:1078
iterator begin()
Return an iterator for the first element in the table.
Definition hashtable.hh:666
size_type bucket_size(bucket_count_type n) const
Return the number of elements in bucket n.
Definition hashtable.hh:647
const_iterator find(key_const_reference key) const
Return an iterator for the element with key key, if any.
Definition hashtable.hh:693
iterator end()
Return an iterator for the end of the table.
Definition hashtable.hh:676
const K & key_const_reference
Const reference to key type.
Definition hashtable.hh:580
iterator find(key_const_reference key)
Definition hashtable.hh:697
const_iterator end() const
Definition hashtable.hh:680
iterator find_insert(key_const_reference key, const mapped_type &value)
Ensure an element for key key and return its iterator.
Definition hashtable.hh:791
HashTable()
Construct an empty hash table with normal default value.
Definition hashtable.hh:596
void swap(HashTable< K, V > &x)
Swap the contents of this hash table and x.
Definition hashtable.hh:841
V mapped_type
Value type.
Definition hashtable.hh:583
const mapped_type & default_value() const
Return the hash table's default value.
Definition hashtable.hh:655
mapped_type & operator[](key_const_reference key)
Return a reference to the value for key.
Definition hashtable.hh:1072
bool operator==(const HashTable_const_iterator< T > &a, const HashTable_const_iterator< T > &b)
Compare two HashTable iterators for equality.
Definition hashtable.hh:1086
bool operator!=(const HashTable_const_iterator< T > &a, const HashTable_const_iterator< T > &b)
Compare two HashTable iterators for inequality.
Definition hashtable.hh:1093