xo-arena: + const_iterator support for DValueHashMap
This commit is contained in:
parent
3711ab21a4
commit
7aa232f1ea
4 changed files with 124 additions and 31 deletions
|
|
@ -50,7 +50,9 @@ namespace xo {
|
|||
using store_type = detail::HashMapStore<Key, Value>;
|
||||
using insert_value_type = std::pair<value_type *, bool>;
|
||||
using iterator = detail::DArenaHashMapIterator<Key, Value>;
|
||||
using const_iterator = detail::DArenaHashMapConstIterator<Key, Value>;
|
||||
|
||||
public:
|
||||
/** create hash map **/
|
||||
DArenaHashMap(size_type hint_max_capacity,
|
||||
bool debug_flag = false);
|
||||
|
|
@ -71,28 +73,14 @@ namespace xo {
|
|||
**/
|
||||
bool verify_ok(verify_policy p = verify_policy::throw_only()) const;
|
||||
|
||||
iterator begin() {
|
||||
if (this->empty()) [[unlikely]] {
|
||||
return this->end();
|
||||
}
|
||||
const_iterator cbegin() const { return this->_begin_aux(); }
|
||||
const_iterator cend() const { return this->_end_aux(); }
|
||||
|
||||
iterator ix(&(store_.control_[c_control_stub]),
|
||||
&(store_.slots_[0]));
|
||||
const_iterator begin() const { return this->_begin_aux(); }
|
||||
const_iterator end() const { return this->_end_aux(); }
|
||||
|
||||
if (ix._at_slot_sentinel()) {
|
||||
/* advance to first occupied position in table */
|
||||
++ix;
|
||||
}
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
iterator ix(&(store_.control_[c_control_stub + store_.capacity()]),
|
||||
&(store_.slots_[store_.capacity()]));
|
||||
|
||||
return ix;
|
||||
}
|
||||
iterator begin() { return _promote_iterator(_begin_aux()); }
|
||||
iterator end() { return _promote_iterator(_end_aux()); }
|
||||
|
||||
/** insert @p kv_pair into hash map.
|
||||
* Replaces any previous value stored under the same key.
|
||||
|
|
@ -117,12 +105,46 @@ namespace xo {
|
|||
/** find element with key @p key.
|
||||
* @return iterator to element if found, end() otherwise
|
||||
**/
|
||||
iterator find(const key_type & key);
|
||||
const_iterator find(const key_type & key) const { return _find(key); }
|
||||
iterator find(const key_type & key) { return _promote_iterator(_find(key)); }
|
||||
|
||||
/** establish kv pair for @p key in this table; return address of value part **/
|
||||
mapped_type & operator[](const key_type & key);
|
||||
|
||||
private:
|
||||
iterator _promote_iterator(const_iterator ix) {
|
||||
return iterator(const_cast<uint8_t *>(ix._ctrl()),
|
||||
const_cast<value_type *>(ix._pos()));
|
||||
}
|
||||
|
||||
const_iterator _begin_aux() const {
|
||||
if (this->empty()) [[unlikely]] {
|
||||
return this->end();
|
||||
}
|
||||
|
||||
const_iterator ix(&(store_.control_[c_control_stub]),
|
||||
&(store_.slots_[0]));
|
||||
|
||||
if (ix._at_slot_sentinel()) {
|
||||
/* advance to first occupied position in table */
|
||||
++ix;
|
||||
}
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
const_iterator _end_aux() const {
|
||||
const_iterator ix(&(store_.control_[c_control_stub + store_.capacity()]),
|
||||
&(store_.slots_[store_.capacity()]));
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
/** search hash map on key @p key, return iterator to table member.
|
||||
* return end-iterator if @p key not found
|
||||
**/
|
||||
const_iterator _find(const key_type & key) const;
|
||||
|
||||
/** insert @p kv_pair,
|
||||
* where key hashes to @p hash_value, into @p *store
|
||||
**/
|
||||
|
|
@ -416,12 +438,12 @@ namespace xo {
|
|||
typename Hash,
|
||||
typename Equal>
|
||||
auto
|
||||
DArenaHashMap<Key, Value, Hash, Equal>::find(const key_type & key) -> iterator
|
||||
DArenaHashMap<Key, Value, Hash, Equal>::_find(const key_type & key) const -> const_iterator
|
||||
{
|
||||
size_type N = store_.capacity();
|
||||
|
||||
if (N == 0) [[unlikely]] {
|
||||
return this->end();
|
||||
return this->cend();
|
||||
}
|
||||
|
||||
size_type h = hash_(key);
|
||||
|
|
@ -443,7 +465,7 @@ namespace xo {
|
|||
auto & slot = store_.slots_[slot_ix];
|
||||
|
||||
if (equal_(slot.first, key)) {
|
||||
return iterator(&(store_.control_[c_control_stub + slot_ix]),
|
||||
return const_iterator(&(store_.control_[c_control_stub + slot_ix]),
|
||||
&slot);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace xo {
|
|||
std::array<uint8_t, DArenaHashMapUtil::c_group_size> ctrl_;
|
||||
|
||||
/** Require: lo is aligned on c_group_size (probably 16 bytes) **/
|
||||
explicit ControlGroup(uint8_t * lo) {
|
||||
explicit ControlGroup(const uint8_t * lo) {
|
||||
::memcpy(ctrl_.data(), lo, DArenaHashMapUtil::c_group_size);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ namespace xo {
|
|||
value_type & operator*() const { return *pos_; }
|
||||
value_type * operator->() const { return pos_; }
|
||||
|
||||
uint8_t * _ctrl() const { return ctrl_; }
|
||||
value_type * _pos() const { return pos_; }
|
||||
|
||||
/** true iff iterator at sentinel position (not dereferencable state !) **/
|
||||
bool _at_slot_sentinel() const { return is_sentinel(*ctrl_) && (*ctrl_ != c_iterator_bookend); }
|
||||
|
||||
|
|
@ -36,8 +39,8 @@ namespace xo {
|
|||
|
||||
DArenaHashMapIterator & operator++() {
|
||||
do {
|
||||
++ctrl_;
|
||||
++pos_;
|
||||
++(this->ctrl_);
|
||||
++(this->pos_);
|
||||
|
||||
/** end condition: iterator ends at last non-wrapped position.
|
||||
* relyin on bookend sentinel values at known offset from 'wrap' section
|
||||
|
|
@ -62,8 +65,8 @@ namespace xo {
|
|||
* precedes control byte for first slot
|
||||
*/
|
||||
do {
|
||||
--ctrl_;
|
||||
--pos_;
|
||||
--(this->ctrl_);
|
||||
--(this->pos_);
|
||||
} while (is_sentinel(*ctrl_)
|
||||
&& (*ctrl_ != c_iterator_bookend));
|
||||
|
||||
|
|
@ -75,6 +78,74 @@ namespace xo {
|
|||
value_type * pos_ = nullptr;
|
||||
};
|
||||
|
||||
template <typename Key,
|
||||
typename Value>
|
||||
struct DArenaHashMapConstIterator : public DArenaHashMapUtil {
|
||||
using value_type = std::pair<const Key, Value>;
|
||||
|
||||
public:
|
||||
DArenaHashMapConstIterator(const uint8_t * c, const value_type * p)
|
||||
: ctrl_{c}, pos_{p} {}
|
||||
|
||||
const value_type & operator*() const { return *pos_; }
|
||||
const value_type * operator->() const { return pos_; }
|
||||
|
||||
const uint8_t * _ctrl() const { return ctrl_; }
|
||||
const value_type * _pos() const { return pos_; }
|
||||
|
||||
/** true iff iterator at sentinel position (not dereferencable state !) **/
|
||||
bool _at_slot_sentinel() const {
|
||||
return is_sentinel(*ctrl_) && (*ctrl_ != c_iterator_bookend);
|
||||
}
|
||||
|
||||
bool operator==(const DArenaHashMapConstIterator & x) const {
|
||||
return this->pos_ == x.pos_;
|
||||
}
|
||||
|
||||
bool operator!=(const DArenaHashMapConstIterator & x) const {
|
||||
return this->pos_ != x.pos_;
|
||||
}
|
||||
|
||||
DArenaHashMapConstIterator & operator++() {
|
||||
do {
|
||||
++(this->ctrl_);
|
||||
++(this->pos_);
|
||||
|
||||
/** end condition: iterator ends at last non-wrapped position.
|
||||
* relyin on bookend sentinel values at known offset from 'wrap' section
|
||||
*
|
||||
* ctrl_ ctrl_ + c_group_size
|
||||
* | |
|
||||
* v v
|
||||
* <----------------- control_size(n_slot) ---------------->
|
||||
* <-stub-> <----------- n_slot ----------> <group> <-stub->
|
||||
* +--------+-------------------------------+-------+--------+
|
||||
* | 0xF0 | empty / data / tombstone | wrap | 0xF0 |
|
||||
* +--------+-------------------------------+-------+--------+
|
||||
**/
|
||||
} while (is_sentinel(*ctrl_)
|
||||
&& (*(ctrl_ + c_group_size) != c_iterator_bookend));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DArenaHashMapConstIterator & operator--() {
|
||||
/* simpler than forward iteration, since bookend immediately
|
||||
* precedes control byte for first slot
|
||||
*/
|
||||
do {
|
||||
--(this->ctrl_);
|
||||
--(this->pos_);
|
||||
} while (is_sentinel(*ctrl_)
|
||||
&& (*ctrl_ != c_iterator_bookend));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t * ctrl_ = nullptr;
|
||||
const value_type * pos_ = nullptr;
|
||||
};
|
||||
}
|
||||
} /*namespace map*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ namespace xo {
|
|||
}
|
||||
|
||||
/** load control group for slot range [ix .. ix+c_group_size) **/
|
||||
group_type _load_group(size_type ix) {
|
||||
group_type _load_group(size_type ix) const {
|
||||
return group_type(&(control_[ix + c_control_stub]));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue