20namespace swoc {
inline namespace SWOC_VERSION_NS {
79 using value_type =
typename std::remove_pointer<
typename std::remove_reference<
decltype(H::next_ptr(
nullptr))>::type>::type;
97 using List = IntrusiveDList<H>;
137 using iterator =
typename List::iterator;
138 using const_iterator =
typename List::const_iterator;
143 struct range :
public std::pair<iterator, iterator> {
145 using super_type::super_type;
153 iterator
const &
end()
const;
157 struct const_range :
public std::pair<const_iterator, const_iterator> {
158 using super_type = std::pair<const_iterator, const_iterator>;
163 using super_type::super_type;
168 const_iterator
const &
begin()
const;
171 const_iterator
const &
end()
const;
191 const_iterator
end()
const;
238 iterator
erase(iterator
const &loc);
244 iterator
erase(iterator
const &start, iterator
const &limit);
261 template <
typename F> self_type &
apply(F &&f);
308 static constexpr std::array<size_t, 29> PRIME = {
309 {1, 3, 7, 13, 31, 61, 127, 251, 509, 1021,
310 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573,
311 2097143, 4194301, 8388593, 16777213, 33554393, 67108859, 134217689, 268435399, 536870909}
318 return b->_link._next;
324 return b->_link._prev;
333 return n ? n->
_v :
nullptr;
343 _link._next = _link._prev =
nullptr;
351 while (x !=
limit && x != v) {
361 return super_type::first;
367 return super_type::second;
373 return super_type::first;
379 return super_type::second;
386 _table.resize(*std::lower_bound(PRIME.begin(), PRIME.end(), n));
392IntrusiveHashMap<H>::bucket_for(key_type key) -> Bucket * {
393 return &_table[H::hash_of(key) % _table.size()];
399 return _list.begin();
405 return _list.begin();
435 Bucket *b = this->bucket_for(key);
436 value_type *v = b->_v;
437 value_type *limit = b->limit();
438 while (v != limit && !H::equal(key, H::key_of(v))) {
441 return v == limit ? _list.end() : _list.iterator_for(v);
447 return const_cast<self_type *
>(
this)->
find(key);
453 iterator first{this->find(key)};
454 iterator last{first};
455 iterator limit{this->end()};
457 while (last != limit && H::equal(key, H::key_of(&*last))) {
461 return range{first, last};
467 return const_cast<self_type *
>(
this)->
equal_range(key);
473 return _list.iterator_for(v);
479 return _list.iterator_for(v);
485 Bucket *b = this->bucket_for(H::key_of(v));
486 return b->contains(v) ? _list.iterator_for(v) : this->end();
492 return const_cast<self_type *
>(
this)->
find(
const_cast<value_type *
>(v));
498 auto key = H::key_of(v);
499 Bucket *bucket = this->bucket_for(key);
501 bool mixed_p =
false;
503 if (
nullptr == spot) {
511 while (spot != limit && !H::equal(key, H::key_of(spot))) {
512 spot = H::next_ptr(spot);
514 if (spot != bucket->
_v) {
520 spot = H::next_ptr(spot);
521 }
while (spot != limit && H::equal(key, H::key_of(spot)));
527 _list.insert_before(spot, v);
528 if (spot == bucket->
_v) {
547 Bucket *b = this->bucket_for(H::key_of(v));
566 auto loc = this->
find(value);
567 if (loc != this->
end()) {
578 Bucket *bucket{this->bucket_for(spot)};
579 while (spot != limit) {
580 auto target = bucket;
581 bucket = bucket->_link._next;
582 value_type *v_limit = bucket ? bucket->_v :
nullptr;
583 while (spot != v_limit && spot != limit) {
587 if (target->_count == 0) {
591 _list.erase(start, limit);
592 return _list.iterator_for(limit);
598 return this->
erase(r.first, r.second);
608template <
typename H,
typename F>
615template <
typename H,
typename F>
617IntrusiveHashMapApply(IntrusiveHashMap<H> &map, F &&f)
618 ->
decltype(f(
static_cast<typename IntrusiveHashMap<H>::value_type *
>(
nullptr)), map) {
619 auto spot{map.begin()};
620 auto limit{map.end()};
621 while (spot != limit) {
631IntrusiveHashMap<H>::apply(F &&f) -> self_type & {
632 return detail::IntrusiveHashMapApply(*
this, f);
640 auto old_size =
_table.size();
644 _table.resize(*std::lower_bound(PRIME.begin(), PRIME.end(), old_size + 1));
649 old = H::next_ptr(old);
659 return _list.count();
bool erase(value_type *value)
const_iterator end() const
Past last element.
void insert(value_type *v)
decltype(H::key_of(static_cast< value_type * >(nullptr))) key_type
Key type for the elements.
const_range equal_range(key_type key) const
ExpansionPolicy
When the hash table is expanded.
@ AVERAGE
Table expands if average chain length exceeds limit. [default].
@ MAXIMUM
Table expands if any chain length exceeds limit.
@ MANUAL
Client must explicitly expand the table.
iterator iterator_for(value_type *v)
ExpansionPolicy get_expansion_policy() const
Get the current expansion policy.
const_iterator begin() const
First element.
List _list
Elements in the table.
self_type & set_expansion_policy(ExpansionPolicy policy)
Set the expansion policy to policy.
size_t bucket_count() const
Number of buckets in the array.
Table _table
Array of buckets.
iterator erase(iterator const &loc)
iterator erase(range const &r)
Remove all elements in the range r.
self_type & set_expansion_limit(size_t n)
Set the limit value for the expansion policy.
size_t get_expansion_limit() const
Set the limit value for the expansion policy.
iterator begin()
First element.
decltype(H::hash_of(H::key_of(static_cast< value_type * >(nullptr)))) hash_id
The numeric hash ID computed from a key.
IntrusiveDList< typename Bucket::Linkage > _active_buckets
List of non-empty buckets.
ExpansionPolicy _expansion_policy
When to exand the table.
static ExpansionPolicy constexpr DEFAULT_EXPANSION_POLICY
Expansion policy if not specified in constructor.
IntrusiveHashMap(size_t n=DEFAULT_BUCKET_COUNT)
const_iterator find(value_type const *v) const
static size_t constexpr DEFAULT_BUCKET_COUNT
The default starting number of buckets.
iterator end()
Past last element.
std::vector< Bucket > Table
The type of storage for the buckets.
IntrusiveHashMap(self_type &&that)=default
Move constructor.
size_t _expansion_limit
Limit value for expansion.
const_iterator find(key_type key) const
typename std::remove_pointer< typename std::remove_reference< decltype(H::next_ptr(nullptr))>::type >::type value_type
Type of elements in the map.
iterator erase(iterator const &start, iterator const &limit)
Remove all elements in the range (start, limit].
size_t count() const
Number of elements in the map.
static size_t constexpr DEFAULT_EXPANSION_LIMIT
The default expansion policy limit.
For template deduction guides.
Support for IntrusiveDList<Bucket::Linkage>, definitions and link storage.
Bucket * _next
Next pointer.
static Bucket *& next_ptr(Bucket *b)
Access next pointer.
Bucket * _prev
Prev pointer.
static Bucket *& prev_ptr(Bucket *b)
Access prev pointer.
A bucket for the hash map.
size_t _count
Number of elements in the bucket.
value_type * _v
First element in the bucket.
bool contains(value_type *v) const
value_type * limit() const
A range of constant elements in the map.
const_iterator const & begin() const
std::pair< const_iterator, const_iterator > super_type
Super type.
const_iterator const & end() const
const_range(range const &r)
Allow implicit conversion of range to const_range.
std::pair< iterator, iterator > super_type
Super type.
iterator const & end() const
iterator const & begin() const