12 #ifndef LIBPMEMOBJ_CPP_RADIX_HPP
13 #define LIBPMEMOBJ_CPP_RADIX_HPP
49 namespace experimental
52 template <
typename T,
typename Enable =
void>
121 template <
typename Key,
typename Value,
typename BytesView =
bytes_view<Key>,
124 template <
bool IsConst>
125 struct radix_tree_iterator;
128 using key_type = Key;
129 using mapped_type = Value;
130 using value_type = detail::pair<const key_type, mapped_type>;
131 using size_type = std::size_t;
132 using reference = value_type &;
133 using const_reference =
const value_type &;
134 using iterator = radix_tree_iterator<false>;
135 using const_iterator = radix_tree_iterator<true>;
136 using reverse_iterator = std::reverse_iterator<iterator>;
137 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
138 using difference_type = std::ptrdiff_t;
140 using worker_type = detail::ebr::worker;
144 template <
class InputIt>
148 radix_tree(std::initializer_list<value_type> il);
156 template <
class... Args>
157 std::pair<iterator, bool> emplace(Args &&... args);
159 std::pair<iterator, bool>
insert(
const value_type &
v);
160 std::pair<iterator, bool>
insert(value_type &&
v);
161 template <
typename P,
162 typename =
typename std::enable_if<
163 std::is_constructible<value_type, P &&>::value,
165 std::pair<iterator, bool>
insert(P &&
p);
173 template <
class InputIterator>
174 void insert(InputIterator first, InputIterator last);
175 void insert(std::initializer_list<value_type> il);
179 template <
class... Args>
180 std::pair<iterator, bool> try_emplace(
const key_type &k,
182 template <
class... Args>
183 std::pair<iterator, bool> try_emplace(key_type &&k, Args &&... args);
191 template <
typename K,
typename BV = BytesView,
class... Args>
192 auto try_emplace(K &&k, Args &&... args) ->
typename std::enable_if<
193 detail::has_is_transparent<BV>::value &&
194 !std::is_same<
typename std::remove_const<
195 typename std::remove_reference<
198 std::pair<iterator, bool>>::type;
200 template <
typename M>
201 std::pair<iterator, bool> insert_or_assign(
const key_type &k, M &&obj);
202 template <
typename M>
203 std::pair<iterator, bool> insert_or_assign(key_type &&k, M &&obj);
210 typename M,
typename K,
211 typename =
typename std::enable_if<
212 detail::has_is_transparent<BytesView>::value, K>::type>
213 std::pair<iterator, bool> insert_or_assign(K &&k, M &&obj);
215 iterator
erase(const_iterator pos);
216 iterator
erase(const_iterator first, const_iterator last);
217 size_type
erase(
const key_type &k);
218 template <
typename K,
219 typename =
typename std::enable_if<
220 detail::has_is_transparent<BytesView>::value &&
221 !std::is_same<K, iterator>::value &&
222 !std::is_same<K, const_iterator>::value,
224 size_type
erase(
const K &k);
228 size_type
count(
const key_type &k)
const;
231 typename =
typename std::enable_if<
232 detail::has_is_transparent<BytesView>::value, K>::type>
233 size_type
count(
const K &k)
const;
235 iterator
find(
const key_type &k);
236 const_iterator
find(
const key_type &k)
const;
239 typename =
typename std::enable_if<
240 detail::has_is_transparent<BytesView>::value, K>::type>
241 iterator
find(
const K &k);
244 typename =
typename std::enable_if<
245 detail::has_is_transparent<BytesView>::value, K>::type>
246 const_iterator
find(
const K &k)
const;
249 const_iterator
lower_bound(
const key_type &k)
const;
252 typename =
typename std::enable_if<
253 detail::has_is_transparent<BytesView>::value, K>::type>
257 typename =
typename std::enable_if<
258 detail::has_is_transparent<BytesView>::value, K>::type>
262 const_iterator
upper_bound(
const key_type &k)
const;
265 typename =
typename std::enable_if<
266 detail::has_is_transparent<BytesView>::value, K>::type>
270 typename =
typename std::enable_if<
271 detail::has_is_transparent<BytesView>::value, K>::type>
276 const_iterator
cbegin()
const;
277 const_iterator
cend()
const;
278 const_iterator
begin()
const;
279 const_iterator
end()
const;
281 reverse_iterator
rbegin();
282 reverse_iterator
rend();
283 const_reverse_iterator
crbegin()
const;
284 const_reverse_iterator
crend()
const;
285 const_reverse_iterator
rbegin()
const;
286 const_reverse_iterator
rend()
const;
289 bool empty()
const noexcept;
290 size_type
max_size()
const noexcept;
291 uint64_t
size()
const noexcept;
295 template <
typename K,
typename V,
typename BV,
bool Mt>
296 friend std::ostream &
operator<<(std::ostream &os,
299 template <
bool Mt = MtMode,
300 typename Enable =
typename std::enable_if<Mt>::type>
302 template <
bool Mt = MtMode,
303 typename Enable =
typename std::enable_if<Mt>::type>
306 template <
bool Mt = MtMode,
307 typename Enable =
typename std::enable_if<Mt>::type>
309 template <
bool Mt = MtMode,
310 typename Enable =
typename std::enable_if<Mt>::type>
313 template <
bool Mt = MtMode,
314 typename Enable =
typename std::enable_if<Mt>::type>
318 using byten_t = uint64_t;
319 using bitn_t = uint8_t;
322 static constexpr std::size_t SLICE = 4;
324 static constexpr std::size_t NIB = ((1ULL << SLICE) - 1);
326 static constexpr std::size_t SLNODES = (1 << SLICE);
328 static constexpr bitn_t SLICE_MASK = (bitn_t) ~(SLICE - 1);
330 static constexpr bitn_t FIRST_NIB = 8 - SLICE;
332 static constexpr
size_t EPOCHS_NUMBER = 3;
337 using pointer_type = detail::tagged_ptr<leaf, node>;
338 using atomic_pointer_type =
339 typename std::conditional<MtMode, std::atomic<pointer_type>,
344 const atomic_pointer_type *slot;
349 using path_type = std::vector<node_desc>;
353 static constexpr
size_t PATH_INIT_CAP = 64;
356 atomic_pointer_type root;
363 template <
typename K,
typename F,
class... Args>
364 std::pair<iterator, bool> internal_emplace(
const K &, F &&);
365 template <
typename K>
366 leaf *internal_find(
const K &k)
const;
368 static atomic_pointer_type &parent_ref(pointer_type n);
369 template <
typename K1,
typename K2>
370 static bool keys_equal(
const K1 &k1,
const K2 &k2);
371 template <
typename K1,
typename K2>
372 static int compare(
const K1 &k1,
const K2 &k2, byten_t offset = 0);
373 template <
bool Direction,
typename Iterator>
374 std::pair<bool, const leaf *> next_leaf(Iterator child,
375 pointer_type parent)
const;
376 template <
bool Direction>
377 const leaf *find_leaf(pointer_type n)
const;
378 static unsigned slice_index(
char k, uint8_t shift);
379 template <
typename K1,
typename K2>
380 static byten_t prefix_diff(
const K1 &lhs,
const K2 &rhs,
382 leaf *any_leftmost_leaf(pointer_type n, size_type min_depth)
const;
383 template <
typename K1,
typename K2>
384 static bitn_t bit_diff(
const K1 &leaf_key,
const K2 &key, byten_t diff);
385 template <
typename K>
386 std::pair<typename radix_tree<Key, Value, BytesView, MtMode>::leaf *,
388 descend(pointer_type n,
const K &key)
const;
389 static void print_rec(std::ostream &os, radix_tree::pointer_type n);
390 template <
typename K>
391 static BytesView bytes_view(
const K &k);
393 static bool path_length_equal(
size_t key_size, pointer_type n);
394 template <
bool Lower,
typename K>
395 bool validate_bound(const_iterator it,
const K &key)
const;
396 node_desc follow_path(
const path_type &, byten_t diff, bitn_t sh)
const;
397 template <
bool Mt = MtMode>
398 typename std::enable_if<Mt, bool>::type
399 validate_path(
const path_type &path)
const;
400 template <
bool Mt = MtMode>
401 typename std::enable_if<!Mt, bool>::type
402 validate_path(
const path_type &path)
const;
403 template <
bool Lower,
typename K>
404 const_iterator internal_bound(
const K &k)
const;
405 static bool is_leaf(
const pointer_type &
p);
406 static leaf *get_leaf(
const pointer_type &
p);
407 static node *get_node(
const pointer_type &
p);
408 template <
typename T>
410 void clear_garbage(
size_t n);
412 load(
const std::atomic<detail::tagged_ptr<leaf, node>> &ptr);
413 static pointer_type load(
const pointer_type &ptr);
414 static void store(std::atomic<detail::tagged_ptr<leaf, node>> &ptr,
415 pointer_type desired);
416 static void store(pointer_type &ptr, pointer_type desired);
418 void check_tx_stage_work();
420 static_assert(
sizeof(
node) == 256,
421 "Internal node should have size equal to 256 bytes.");
424 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
437 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
452 const Key &key()
const;
453 const Value &value()
const;
457 template <
typename... Args1,
typename... Args2>
459 make(pointer_type parent, std::piecewise_construct_t pc,
460 std::tuple<Args1...> first_args, std::tuple<Args2...> second_args);
461 template <
typename K,
typename V>
465 template <
typename K,
typename... Args>
468 template <
typename K,
typename V>
470 detail::pair<K, V> &&
p);
471 template <
typename K,
typename V>
473 const detail::pair<K, V> &
p);
474 template <
typename K,
typename V>
476 std::pair<K, V> &&
p);
477 template <
typename K,
typename V>
479 const std::pair<K, V> &
p);
484 friend class radix_tree<Key, Value, BytesView, MtMode>;
488 template <
typename... Args1,
typename... Args2,
size_t... I1,
491 make(pointer_type parent, std::piecewise_construct_t,
492 std::tuple<Args1...> &first_args,
493 std::tuple<Args2...> &second_args, detail::index_sequence<I1...>,
494 detail::index_sequence<I2...>);
496 atomic_pointer_type parent;
503 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
505 node(pointer_type parent, byten_t
byte, bitn_t bit);
521 atomic_pointer_type child[SLNODES];
537 static constexpr
bool Forward = 0;
538 static constexpr
bool Reverse = 1;
541 struct forward_iterator;
542 using reverse_iterator = std::reverse_iterator<forward_iterator>;
544 template <
bool Direction>
546 typename std::conditional<Direction == direction::Forward,
548 reverse_iterator>::type;
550 template <
bool Direction = direction::Forward>
551 typename std::enable_if<
554 MtMode>::node::direction::Forward,
556 MtMode>::node::forward_iterator>::type
559 template <
bool Direction = direction::Forward>
560 typename std::enable_if<
563 MtMode>::node::direction::Forward,
565 MtMode>::node::forward_iterator>::type
569 template <
bool Direction = direction::Forward>
570 typename std::enable_if<
573 MtMode>::node::direction::Reverse,
575 MtMode>::node::reverse_iterator>::type
579 template <
bool Direction = direction::Forward>
580 typename std::enable_if<
583 MtMode>::node::direction::Reverse,
585 MtMode>::node::reverse_iterator>::type
588 template <
bool Direction = direction::Forward,
typename Ptr>
589 iterator<Direction> find_child(
const Ptr &n)
const;
591 template <
bool Direction = direction::Forward,
592 typename Enable =
typename std::enable_if<
593 Direction == direction::Forward>::type>
594 iterator<Direction> make_iterator(
const atomic_pointer_type *ptr)
const;
596 uint8_t padding[256 -
sizeof(parent) -
sizeof(
leaf) -
sizeof(child) -
597 sizeof(
byte) -
sizeof(bit)];
605 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
606 template <
bool IsConst>
607 struct radix_tree<Key, Value, BytesView, MtMode>::radix_tree_iterator {
610 typename std::conditional<IsConst, const leaf *, leaf *>::type;
611 using tree_ptr =
typename std::conditional<IsConst,
const radix_tree *,
613 friend struct radix_tree_iterator<true>;
616 using difference_type = std::ptrdiff_t;
618 using reference =
typename std::conditional<IsConst,
const value_type &,
620 using pointer =
typename std::conditional<IsConst, value_type
const *,
622 using iterator_category =
typename std::conditional<
623 MtMode, std::forward_iterator_tag,
624 std::bidirectional_iterator_tag>::type;
626 radix_tree_iterator() =
default;
627 radix_tree_iterator(leaf_ptr leaf_, tree_ptr tree);
628 radix_tree_iterator(
const radix_tree_iterator &rhs) =
default;
630 template <
bool C = IsConst,
631 typename Enable =
typename std::enable_if<C>::type>
632 radix_tree_iterator(
const radix_tree_iterator<false> &rhs);
634 radix_tree_iterator &
635 operator=(
const radix_tree_iterator &rhs) =
default;
637 reference operator*()
const;
638 pointer operator->()
const;
640 template <
typename V = Value,
641 typename Enable =
typename std::enable_if<
642 detail::is_inline_string<V>::value>::type>
644 typename V::traits_type>
647 template <
typename T,
typename V = Value,
648 typename Enable =
typename std::enable_if<
649 !detail::is_inline_string<V>::value>::type>
650 void assign_val(T &&rhs);
652 radix_tree_iterator &operator++();
653 template <
bool Mt = MtMode,
654 typename Enable =
typename std::enable_if<!Mt>::type>
655 radix_tree_iterator &operator--();
657 radix_tree_iterator operator++(
int);
658 template <
bool Mt = MtMode,
659 typename Enable =
typename std::enable_if<!Mt>::type>
660 radix_tree_iterator operator--(
int);
663 bool operator!=(
const radix_tree_iterator<C> &rhs)
const;
666 bool operator==(
const radix_tree_iterator<C> &rhs)
const;
671 leaf_ptr leaf_ =
nullptr;
672 tree_ptr tree =
nullptr;
674 template <
typename T>
675 void replace_val(T &&rhs);
677 bool try_increment();
678 bool try_decrement();
681 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
682 struct radix_tree<Key, Value, BytesView, MtMode>::node::forward_iterator {
683 using difference_type = std::ptrdiff_t;
684 using value_type = atomic_pointer_type;
685 using pointer =
const value_type *;
686 using reference =
const value_type &;
687 using iterator_category = std::forward_iterator_tag;
689 forward_iterator(pointer child,
const node *node);
691 forward_iterator operator++();
692 forward_iterator operator++(
int);
694 forward_iterator operator--();
696 reference operator*()
const;
697 pointer operator->()
const;
699 pointer get_node()
const;
701 bool operator!=(
const forward_iterator &rhs)
const;
702 bool operator==(
const forward_iterator &rhs)
const;
717 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
719 : root(nullptr), size_(0)
722 check_tx_stage_work();
744 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
745 template <
class InputIt>
748 : root(nullptr), size_(0)
751 check_tx_stage_work();
753 for (
auto it = first; it != last; it++)
772 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
774 : root(nullptr), size_(0)
777 check_tx_stage_work();
779 for (
auto it = m.cbegin(); it != m.cend(); it++)
795 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
799 check_tx_stage_work();
801 store(root, load(m.root));
803 store(m.root,
nullptr);
821 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
823 std::initializer_list<value_type> il)
837 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
845 if (
this != &other) {
849 store(this->root,
nullptr);
852 for (
auto it = other.cbegin(); it != other.cend(); it++)
868 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
876 if (
this != &other) {
880 store(this->root, load(other.root));
881 this->size_ = other.size_;
882 store(other.root,
nullptr);
900 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
903 std::initializer_list<value_type> ilist)
912 store(this->root,
nullptr);
915 for (
auto it = ilist.begin(); it != ilist.end(); it++)
925 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
930 for (
size_t i = 0; i < EPOCHS_NUMBER; ++i)
942 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
952 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
953 typename radix_tree<Key, Value, BytesView, MtMode>::size_type
956 return std::numeric_limits<difference_type>::max();
962 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
974 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
981 this->size_.swap(rhs.size_);
982 this->root.swap(rhs.root);
995 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
996 template <
bool Mt,
typename Enable>
1001 for (
size_t i = 0; i < EPOCHS_NUMBER; ++i) {
1016 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1017 template <
bool Mt,
typename Enable>
1022 clear_garbage(ebr_->gc_epoch());
1025 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1029 assert(n >= 0 && n < EPOCHS_NUMBER);
1034 for (
auto &e : garbages[n]) {
1036 delete_persistent<radix_tree::leaf>(
1040 delete_persistent<radix_tree::node>(
1045 garbages[n].clear();
1049 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1050 typename radix_tree<Key, Value, BytesView, MtMode>::pointer_type
1051 radix_tree<Key, Value, BytesView, MtMode>::load(
1052 const std::atomic<detail::tagged_ptr<leaf, node>> &ptr)
1054 return ptr.load_acquire();
1057 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1058 typename radix_tree<Key, Value, BytesView, MtMode>::pointer_type
1059 radix_tree<Key, Value, BytesView, MtMode>::load(
const pointer_type &ptr)
1064 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1066 radix_tree<Key, Value, BytesView, MtMode>::store(
1067 std::atomic<detail::tagged_ptr<leaf, node>> &ptr, pointer_type desired)
1069 ptr.store_with_snapshot_release(desired);
1072 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1074 radix_tree<Key, Value, BytesView, MtMode>::store(pointer_type &ptr,
1075 pointer_type desired)
1088 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1089 template <
bool Mt,
typename Enable>
1093 #if LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED
1094 VALGRIND_PMC_REMOVE_PMEM_MAPPING(&ebr_,
sizeof(
ebr *));
1103 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1104 template <
bool Mt,
typename Enable>
1122 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1123 template <
bool Mt,
typename Enable>
1124 typename radix_tree<Key, Value, BytesView, MtMode>::worker_type
1129 return ebr_->register_worker();
1135 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1136 typename radix_tree<Key, Value, BytesView, MtMode>::atomic_pointer_type &
1140 return get_leaf(n)->parent;
1153 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1154 typename radix_tree<Key, Value, BytesView, MtMode>::leaf *
1155 radix_tree<Key, Value, BytesView, MtMode>::any_leftmost_leaf(
1156 typename radix_tree<Key, Value, BytesView, MtMode>::pointer_type n,
1157 size_type min_depth)
const
1161 while (n && !is_leaf(n)) {
1162 auto ne = load(n->embedded_entry);
1163 if (ne && n->byte >= min_depth)
1164 return get_leaf(ne);
1166 pointer_type nn =
nullptr;
1167 for (
size_t i = 0; i < SLNODES; i++) {
1168 nn = load(n->child[i]);
1177 return n ? get_leaf(n) : nullptr;
1191 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1192 template <
typename K>
1193 std::pair<typename radix_tree<Key, Value, BytesView, MtMode>::leaf *,
1194 typename radix_tree<Key, Value, BytesView, MtMode>::path_type>
1195 radix_tree<Key, Value, BytesView, MtMode>::descend(pointer_type root_snap,
1200 auto slot = &this->root;
1202 decltype(n) prev =
nullptr;
1205 path.reserve(PATH_INIT_CAP);
1206 path.push_back(node_desc{slot, n, prev});
1208 while (n && !is_leaf(n) && n->byte < key.size()) {
1210 slot = &n->child[slice_index(key[n->byte], n->bit)];
1211 auto nn = load(*slot);
1214 path.push_back(node_desc{slot, nn, prev});
1217 path.push_back(node_desc{slot,
nullptr, prev});
1218 n = any_leftmost_leaf(n, key.size());
1224 return {
nullptr, std::move(path)};
1229 n = any_leftmost_leaf(n, key.size());
1233 return std::pair<leaf *, path_type>{get_leaf(n),
1236 return std::pair<leaf *, path_type>{
nullptr, std::move(path)};
1240 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1241 template <
typename K>
1243 radix_tree<Key, Value, BytesView, MtMode>::bytes_view(
const K &key)
1248 return BytesView(&key);
1251 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1253 radix_tree<Key, Value, BytesView, MtMode>::bytes_view(
string_view key)
1261 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1262 template <
typename K1,
typename K2>
1264 radix_tree<Key, Value, BytesView, MtMode>::keys_equal(
const K1 &k1,
1267 return k1.size() == k2.size() && compare(k1, k2) == 0;
1273 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1274 template <
typename K1,
typename K2>
1276 radix_tree<Key, Value, BytesView, MtMode>::compare(
const K1 &k1,
const K2 &k2,
1279 auto ret = prefix_diff(k1, k2, offset);
1281 if (ret != (std::min)(k1.size(), k2.size()))
1282 return (
unsigned char)(k1[ret]) - (
unsigned char)(k2[ret]);
1284 return k1.size() - k2.size();
1290 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1291 template <
typename K1,
typename K2>
1292 typename radix_tree<Key, Value, BytesView, MtMode>::byten_t
1293 radix_tree<Key, Value, BytesView, MtMode>::prefix_diff(
const K1 &lhs,
1298 for (diff = offset; diff < (std::min)(lhs.size(), rhs.size()); diff++) {
1299 if (lhs[diff] != rhs[diff])
1310 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1312 radix_tree<Key, Value, BytesView, MtMode>::path_length_equal(
size_t key_size,
1315 return n->byte == key_size && n->bit == bitn_t(FIRST_NIB);
1318 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1319 template <
typename K1,
typename K2>
1320 typename radix_tree<Key, Value, BytesView, MtMode>::bitn_t
1321 radix_tree<Key, Value, BytesView, MtMode>::bit_diff(
const K1 &leaf_key,
1322 const K2 &key, byten_t diff)
1324 auto min_key_len = (std::min)(leaf_key.size(), key.size());
1330 if (diff < min_key_len) {
1332 static_cast<unsigned char>(leaf_key[diff] ^ key[diff]);
1343 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1344 typename radix_tree<Key, Value, BytesView, MtMode>::node_desc
1345 radix_tree<Key, Value, BytesView, MtMode>::follow_path(
const path_type &path,
1349 assert(path.size());
1354 while (n.node && !is_leaf(n.node) &&
1355 (n.node->byte < diff ||
1356 (n.node->byte == diff && n.node->bit >= sh))) {
1359 assert(idx < path.size());
1367 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1368 template <
typename K,
typename F,
class... Args>
1369 std::pair<typename radix_tree<Key, Value, BytesView, MtMode>::iterator,
bool>
1370 radix_tree<Key, Value, BytesView, MtMode>::internal_emplace(
const K &k,
1373 auto key = bytes_view(k);
1374 auto pop = pool_base(pmemobj_pool_by_ptr(
this));
1376 auto r = load(root);
1380 leaf = make_leaf(
nullptr);
1381 store(this->root, leaf);
1383 return {iterator(get_leaf(leaf),
this),
true};
1393 auto ret = descend(r, key);
1394 auto leaf = ret.first;
1395 auto path = ret.second;
1399 auto leaf_key = bytes_view(leaf->key());
1400 auto diff = prefix_diff(key, leaf_key);
1401 auto sh = bit_diff(leaf_key, key, diff);
1404 if (diff == key.size() && leaf_key.size() == key.size())
1405 return {iterator(leaf,
this),
false};
1408 auto node_d = follow_path(path, diff, sh);
1409 auto slot =
const_cast<atomic_pointer_type *
>(node_d.slot);
1410 auto prev = node_d.prev;
1411 auto n = node_d.node;
1419 assert(diff < (std::min)(leaf_key.size(), key.size()));
1422 [&] { store(*slot, make_leaf(prev)); });
1423 return {iterator(get_leaf(load(*slot)),
this),
true};
1428 if (diff == key.size()) {
1429 if (!is_leaf(n) && path_length_equal(key.size(), n)) {
1430 assert(!load(n->embedded_entry));
1433 store(n->embedded_entry, make_leaf(n));
1436 return {iterator(get_leaf(load(n->embedded_entry)),
1445 node = make_persistent<radix_tree::node>(
1446 load(parent_ref(n)), diff, bitn_t(FIRST_NIB));
1447 store(node->embedded_entry, make_leaf(node));
1448 store(node->child[slice_index(leaf_key[diff],
1449 bitn_t(FIRST_NIB))],
1452 store(parent_ref(n), node);
1456 return {iterator(get_leaf(load(node->embedded_entry)),
this),
1460 if (diff == leaf_key.size()) {
1467 node = make_persistent<radix_tree::node>(
1468 load(parent_ref(n)), diff, bitn_t(FIRST_NIB));
1469 store(node->embedded_entry, n);
1470 store(node->child[slice_index(key[diff],
1471 bitn_t(FIRST_NIB))],
1474 store(parent_ref(n), node);
1478 return {iterator(get_leaf(load(node->child[slice_index(
1479 key[diff], bitn_t(FIRST_NIB))])),
1490 node = make_persistent<radix_tree::node>(load(parent_ref(n)),
1492 store(node->child[slice_index(leaf_key[diff], sh)], n);
1493 store(node->child[slice_index(key[diff], sh)], make_leaf(node));
1495 store(parent_ref(n), node);
1500 get_leaf(load(node->child[slice_index(key[diff], sh)])),
1533 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1534 template <
class... Args>
1535 std::pair<typename radix_tree<Key, Value, BytesView, MtMode>::iterator,
bool>
1539 return internal_emplace(k, [&](pointer_type parent) {
1541 return leaf::make_key_args(parent, k,
1542 std::forward<Args>(args)...);
1572 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1573 template <
class... Args>
1574 std::pair<typename radix_tree<Key, Value, BytesView, MtMode>::iterator,
bool>
1577 auto pop =
pool_base(pmemobj_pool_by_ptr(
this));
1578 std::pair<iterator, bool> ret;
1581 auto leaf_ = leaf::make(
nullptr, std::forward<Args>(args)...);
1582 auto make_leaf = [&](pointer_type parent) {
1583 store(leaf_->parent, parent);
1588 ret = internal_emplace(leaf_->key(), make_leaf);
1591 delete_persistent<leaf>(leaf_);
1612 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1613 std::pair<typename radix_tree<Key, Value, BytesView, MtMode>::iterator,
bool>
1616 return try_emplace(
v.first,
v.second);
1634 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1635 std::pair<typename radix_tree<Key, Value, BytesView, MtMode>::iterator,
bool>
1638 return try_emplace(std::move(
v.first), std::move(
v.second));
1660 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1661 template <
typename P,
typename>
1662 std::pair<typename radix_tree<Key, Value, BytesView, MtMode>::iterator,
bool>
1665 return emplace(std::forward<P>(
p));
1679 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1680 template <
typename InputIterator>
1685 for (
auto it = first; it != last; it++)
1686 try_emplace((*it).first, (*it).second);
1699 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1702 std::initializer_list<value_type> il)
1704 insert(il.begin(), il.end());
1731 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1732 template <
class... Args>
1733 std::pair<typename radix_tree<Key, Value, BytesView, MtMode>::iterator,
bool>
1737 return internal_emplace(k, [&](pointer_type parent) {
1739 return leaf::make_key_args(parent, std::move(k),
1740 std::forward<Args>(args)...);
1772 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1773 template <
typename K,
typename BV,
class... Args>
1776 ->
typename std::enable_if<
1777 detail::has_is_transparent<BV>::value &&
1778 !std::is_same<
typename std::remove_const<
1779 typename std::remove_reference<
1782 std::pair<
typename radix_tree<Key, Value, BytesView,
1787 return internal_emplace(k, [&](pointer_type parent) {
1789 return leaf::make_key_args(parent, std::forward<K>(k),
1790 std::forward<Args>(args)...);
1812 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1813 template <
typename M>
1814 std::pair<typename radix_tree<Key, Value, BytesView, MtMode>::iterator,
bool>
1818 auto ret = try_emplace(k, std::forward<M>(obj));
1820 ret.first.assign_val(std::forward<M>(obj));
1842 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1843 template <
typename M>
1844 std::pair<typename radix_tree<Key, Value, BytesView, MtMode>::iterator,
bool>
1848 auto ret = try_emplace(std::move(k), std::forward<M>(obj));
1850 ret.first.assign_val(std::forward<M>(obj));
1875 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1876 template <
typename M,
typename K,
typename>
1877 std::pair<typename radix_tree<Key, Value, BytesView, MtMode>::iterator,
bool>
1880 auto ret = try_emplace(std::forward<K>(k), std::forward<M>(obj));
1882 ret.first.assign_val(std::forward<M>(obj));
1895 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1896 typename radix_tree<Key, Value, BytesView, MtMode>::size_type
1899 return internal_find(k) !=
nullptr ? 1 : 0;
1914 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1915 template <
typename K,
typename>
1916 typename radix_tree<Key, Value, BytesView, MtMode>::size_type
1919 return internal_find(k) !=
nullptr ? 1 : 0;
1930 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1931 typename radix_tree<Key, Value, BytesView, MtMode>::iterator
1934 return iterator(internal_find(k),
this);
1945 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1946 typename radix_tree<Key, Value, BytesView, MtMode>::const_iterator
1949 return const_iterator(internal_find(k),
this);
1963 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1964 template <
typename K,
typename>
1965 typename radix_tree<Key, Value, BytesView, MtMode>::iterator
1968 return iterator(internal_find(k),
this);
1982 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1983 template <
typename K,
typename>
1984 typename radix_tree<Key, Value, BytesView, MtMode>::const_iterator
1987 return const_iterator(internal_find(k),
this);
1990 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
1991 template <
typename K>
1995 auto key = bytes_view(k);
1997 auto n = load(root);
1998 while (n && !is_leaf(n)) {
1999 if (path_length_equal(key.size(), n))
2000 n = load(n->embedded_entry);
2001 else if (n->byte >= key.size())
2004 n = load(n->child[slice_index(key[n->byte], n->bit)]);
2010 if (!keys_equal(key, bytes_view(get_leaf(n)->key())))
2023 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2028 erase(begin(), end());
2046 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2047 typename radix_tree<Key, Value, BytesView, MtMode>::iterator
2050 auto pop =
pool_base(pmemobj_pool_by_ptr(
this));
2053 auto *
leaf = pos.leaf_;
2054 auto parent = load(
leaf->parent);
2066 store(this->root,
nullptr);
2072 store(
const_cast<atomic_pointer_type &
>(
2073 *parent->find_child(
leaf)),
2078 parent = load(n->parent);
2079 pointer_type only_child =
nullptr;
2080 for (
size_t i = 0; i < SLNODES; i++) {
2081 if (load(n->child[i])) {
2086 only_child = load(n->child[i]);
2090 if (only_child && load(n->embedded_entry)) {
2094 }
else if (load(n->embedded_entry)) {
2095 only_child = load(n->embedded_entry);
2099 store(parent_ref(only_child), load(n->parent));
2101 auto *child_slot = parent ?
const_cast<atomic_pointer_type *
>(
2102 &*parent->find_child(n))
2104 store(*child_slot, only_child);
2109 return iterator(
const_cast<typename iterator::leaf_ptr
>(pos.leaf_),
2126 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2127 typename radix_tree<Key, Value, BytesView, MtMode>::iterator
2129 const_iterator last)
2131 auto pop =
pool_base(pmemobj_pool_by_ptr(
this));
2134 while (first != last)
2135 first = erase(first);
2138 return iterator(
const_cast<typename iterator::leaf_ptr
>(first.leaf_),
2154 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2155 typename radix_tree<Key, Value, BytesView, MtMode>::size_type
2158 auto it = const_iterator(internal_find(k),
this);
2182 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2183 template <
typename K,
typename>
2184 typename radix_tree<Key, Value, BytesView, MtMode>::size_type
2187 auto it = const_iterator(internal_find(k),
this);
2201 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2202 template <
typename T>
2206 if (MtMode && ebr_ !=
nullptr)
2207 garbages[ebr_->staging_epoch()].emplace_back(ptr);
2209 delete_persistent<T>(ptr);
2216 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2217 template <
bool Lower,
typename K>
2219 radix_tree<Key, Value, BytesView, MtMode>::validate_bound(const_iterator it,
2226 return (compare(bytes_view(it->key()), bytes_view(key)) >= 0);
2228 return (compare(bytes_view(it->key()), bytes_view(key)) > 0);
2234 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2236 typename std::enable_if<Mt, bool>::type
2237 radix_tree<Key, Value, BytesView, MtMode>::validate_path(
2238 const path_type &path)
const
2240 for (
auto i = 0ULL; i < path.size(); i++) {
2241 if (path[i].node != load(*path[i].slot))
2245 load(parent_ref(path[i].node)) != path[i].prev)
2252 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2254 typename std::enable_if<!Mt, bool>::type
2255 radix_tree<Key, Value, BytesView, MtMode>::validate_path(
2256 const path_type &path)
const
2261 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2262 template <
bool Lower,
typename K>
2263 typename radix_tree<Key, Value, BytesView, MtMode>::const_iterator
2264 radix_tree<Key, Value, BytesView, MtMode>::internal_bound(
const K &k)
const
2266 auto key = bytes_view(k);
2267 auto pop = pool_base(pmemobj_pool_by_ptr(
this));
2270 const_iterator result;
2273 auto r = load(root);
2285 auto ret = descend(r, key);
2286 auto leaf = ret.first;
2292 auto leaf_key = bytes_view(leaf->key());
2293 auto diff = prefix_diff(key, leaf_key);
2294 auto sh = bit_diff(leaf_key, key, diff);
2297 if (diff == key.size() && leaf_key.size() == key.size()) {
2298 result = const_iterator(leaf,
this);
2305 if (result.try_increment())
2312 auto node_d = follow_path(path, diff, sh);
2314 auto n = node_d.node;
2315 auto slot = node_d.slot;
2316 auto prev = node_d.prev;
2324 assert(prev && !is_leaf(prev));
2326 auto target_leaf = next_leaf<node::direction::Forward>(
2327 prev->template make_iterator<
2328 node::direction::Forward>(slot),
2331 if (!target_leaf.first)
2334 result = const_iterator(target_leaf.second,
this);
2335 }
else if (diff == key.size()) {
2343 find_leaf<node::direction::Forward>(n);
2348 result = const_iterator(target_leaf,
this);
2349 }
else if (diff == leaf_key.size()) {
2365 auto target_leaf = next_leaf<
2366 node::direction::Forward>(
2367 prev->template make_iterator<
2368 node::direction::Forward>(slot),
2371 if (!target_leaf.first)
2374 result = const_iterator(target_leaf.second,
2378 assert(diff < leaf_key.size() && diff < key.size());
2404 if (
static_cast<unsigned char>(key[diff]) <
2405 static_cast<unsigned char>(leaf_key[diff])) {
2407 find_leaf<node::direction::Forward>(n);
2412 result = const_iterator(target_leaf,
this);
2413 }
else if (slot == &root) {
2414 result = const_iterator(
nullptr,
this);
2417 assert(
static_cast<unsigned char>(key[diff]) >
2418 static_cast<unsigned char>(
2431 auto target_leaf = next_leaf<
2432 node::direction::Forward>(
2433 prev->template make_iterator<
2434 node::direction::Forward>(slot),
2437 if (!target_leaf.first)
2440 result = const_iterator(target_leaf.second,
2447 if (validate_path(path))
2451 assert(validate_bound<Lower>(result, k));
2466 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2467 typename radix_tree<Key, Value, BytesView, MtMode>::const_iterator
2470 return internal_bound<true>(k);
2483 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2484 typename radix_tree<Key, Value, BytesView, MtMode>::iterator
2487 auto it =
const_cast<const radix_tree *
>(
this)->lower_bound(k);
2488 return iterator(
const_cast<typename iterator::leaf_ptr
>(it.leaf_),
2505 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2506 template <
typename K,
typename>
2507 typename radix_tree<Key, Value, BytesView, MtMode>::iterator
2510 auto it =
const_cast<const radix_tree *
>(
this)->lower_bound(k);
2511 return iterator(
const_cast<typename iterator::leaf_ptr
>(it.leaf_),
2528 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2529 template <
typename K,
typename>
2530 typename radix_tree<Key, Value, BytesView, MtMode>::const_iterator
2533 return internal_bound<true>(k);
2546 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2547 typename radix_tree<Key, Value, BytesView, MtMode>::const_iterator
2550 return internal_bound<false>(k);
2563 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2564 typename radix_tree<Key, Value, BytesView, MtMode>::iterator
2567 auto it =
const_cast<const radix_tree *
>(
this)->upper_bound(k);
2568 return iterator(
const_cast<typename iterator::leaf_ptr
>(it.leaf_),
2585 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2586 template <
typename K,
typename>
2587 typename radix_tree<Key, Value, BytesView, MtMode>::iterator
2590 auto it =
const_cast<const radix_tree *
>(
this)->upper_bound(k);
2591 return iterator(
const_cast<typename iterator::leaf_ptr
>(it.leaf_),
2608 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2609 template <
typename K,
typename>
2610 typename radix_tree<Key, Value, BytesView, MtMode>::const_iterator
2613 return internal_bound<false>(k);
2622 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2623 typename radix_tree<Key, Value, BytesView, MtMode>::iterator
2626 auto const_begin =
const_cast<const radix_tree *
>(
this)->begin();
2628 const_cast<typename iterator::leaf_ptr
>(const_begin.leaf_),
2639 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2640 typename radix_tree<Key, Value, BytesView, MtMode>::iterator
2643 auto const_end =
const_cast<const radix_tree *
>(
this)->end();
2645 const_cast<typename iterator::leaf_ptr
>(const_end.leaf_),
this);
2654 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2655 typename radix_tree<Key, Value, BytesView, MtMode>::const_iterator
2659 auto root_ptr = load(root);
2661 return const_iterator(
nullptr,
this);
2663 auto leaf = find_leaf<radix_tree::node::direction::Forward>(
2666 return const_iterator(
leaf,
this);
2678 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2679 typename radix_tree<Key, Value, BytesView, MtMode>::const_iterator
2682 return const_iterator(
nullptr,
this);
2691 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2692 typename radix_tree<Key, Value, BytesView, MtMode>::const_iterator
2705 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2706 typename radix_tree<Key, Value, BytesView, MtMode>::const_iterator
2719 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2720 typename radix_tree<Key, Value, BytesView, MtMode>::reverse_iterator
2723 return reverse_iterator(end());
2734 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2735 typename radix_tree<Key, Value, BytesView, MtMode>::reverse_iterator
2738 return reverse_iterator(begin());
2748 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2749 typename radix_tree<Key, Value, BytesView, MtMode>::const_reverse_iterator
2752 return const_reverse_iterator(cend());
2763 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2764 typename radix_tree<Key, Value, BytesView, MtMode>::const_reverse_iterator
2767 return const_reverse_iterator(cbegin());
2770 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2771 typename radix_tree<Key, Value, BytesView, MtMode>::const_reverse_iterator
2774 return const_reverse_iterator(cend());
2777 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2778 typename radix_tree<Key, Value, BytesView, MtMode>::const_reverse_iterator
2781 return const_reverse_iterator(cbegin());
2784 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2786 radix_tree<Key, Value, BytesView, MtMode>::print_rec(std::ostream &os,
2787 radix_tree::pointer_type n)
2790 os <<
"\"" << get_node(n) <<
"\""
2791 <<
" [style=filled,color=\"blue\"]" << std::endl;
2792 os <<
"\"" << get_node(n) <<
"\" [label=\"byte:" << n->byte
2793 <<
", bit:" << int(n->bit) <<
"\"]" << std::endl;
2795 auto p = load(n->parent);
2796 auto parent = p ? get_node(p) : 0;
2797 os <<
"\"" << get_node(n) <<
"\" -> "
2798 <<
"\"" << parent <<
"\" [label=\"parent\"]" << std::endl;
2800 for (
auto it = n->begin(); it != n->end(); ++it) {
2806 auto ch = is_leaf(c) ? (
void *)get_leaf(c)
2807 : (
void *)get_node(c);
2809 os <<
"\"" << get_node(n) <<
"\" -> \"" << ch <<
"\""
2814 auto bv = bytes_view(get_leaf(n)->key());
2816 os <<
"\"" << get_leaf(n) <<
"\" [style=filled,color=\"green\"]"
2818 os <<
"\"" << get_leaf(n) <<
"\" [label=\"key:";
2820 for (
size_t i = 0; i < bv.size(); i++)
2823 os <<
"\"]" << std::endl;
2825 auto p = load(get_leaf(n)->parent);
2826 auto parent = p ? get_node(p) : nullptr;
2828 os <<
"\"" << get_leaf(n) <<
"\" -> \"" << parent
2829 <<
"\" [label=\"parent\"]" << std::endl;
2831 if (parent && n == load(parent->embedded_entry)) {
2832 os <<
"{rank=same;\"" << parent <<
"\";\""
2833 << get_leaf(n) <<
"\"}" << std::endl;
2841 template <
typename K,
typename V,
typename BV,
bool MtMode>
2845 os <<
"digraph Radix {" << std::endl;
2851 os <<
"}" << std::endl;
2859 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2861 radix_tree<Key, Value, BytesView, MtMode>::slice_index(
char b, uint8_t bit)
2863 return static_cast<unsigned>(b >> bit) & NIB;
2866 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2867 radix_tree<Key, Value, BytesView,
2868 MtMode>::node::forward_iterator::forward_iterator(pointer child,
2870 : child(child), n(n)
2874 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2875 typename radix_tree<Key, Value, BytesView, MtMode>::node::forward_iterator
2876 radix_tree<Key, Value, BytesView, MtMode>::node::forward_iterator::operator++()
2878 if (child == &n->embedded_entry)
2879 child = &n->child[0];
2886 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2887 radix_tree<Key, Value, BytesView, MtMode>::node::node(pointer_type parent,
2888 byten_t
byte, bitn_t bit)
2889 : parent(parent), byte(byte), bit(bit)
2893 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2894 typename radix_tree<Key, Value, BytesView, MtMode>::node::forward_iterator
2895 radix_tree<Key, Value, BytesView, MtMode>::node::forward_iterator::operator--()
2897 if (child == &n->child[0])
2898 child = &n->embedded_entry;
2905 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2906 typename radix_tree<Key, Value, BytesView, MtMode>::node::forward_iterator
2907 radix_tree<Key, Value, BytesView, MtMode>::node::forward_iterator::operator++(
2910 forward_iterator tmp(child, n);
2915 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2916 typename radix_tree<Key, Value, BytesView,
2917 MtMode>::node::forward_iterator::reference
2918 radix_tree<Key, Value, BytesView,
2919 MtMode>::node::forward_iterator::operator*()
const
2924 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2925 typename radix_tree<Key, Value, BytesView,
2926 MtMode>::node::forward_iterator::pointer
2927 radix_tree<Key, Value, BytesView,
2928 MtMode>::node::forward_iterator::operator->()
const
2933 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2934 typename radix_tree<Key, Value, BytesView,
2935 MtMode>::node::forward_iterator::pointer
2936 radix_tree<Key, Value, BytesView, MtMode>::node::forward_iterator::get_node()
2942 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2944 radix_tree<Key, Value, BytesView, MtMode>::node::forward_iterator::operator==(
2945 const forward_iterator &rhs)
const
2947 return child == rhs.child && n == rhs.n;
2950 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2952 radix_tree<Key, Value, BytesView, MtMode>::node::forward_iterator::operator!=(
2953 const forward_iterator &rhs)
const
2955 return child != rhs.child || n != rhs.n;
2958 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2959 template <
bool Direction>
2960 typename std::enable_if<Direction ==
2961 radix_tree<Key, Value, BytesView,
2962 MtMode>::node::direction::Forward,
2963 typename radix_tree<Key, Value, BytesView, MtMode>::
2964 node::forward_iterator>::type
2965 radix_tree<Key, Value, BytesView, MtMode>::node::begin()
const
2967 return forward_iterator(&embedded_entry,
this);
2970 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2971 template <
bool Direction>
2972 typename std::enable_if<Direction ==
2973 radix_tree<Key, Value, BytesView,
2974 MtMode>::node::direction::Forward,
2975 typename radix_tree<Key, Value, BytesView, MtMode>::
2976 node::forward_iterator>::type
2977 radix_tree<Key, Value, BytesView, MtMode>::node::end()
const
2979 return forward_iterator(&child[SLNODES],
this);
2982 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2983 template <
bool Direction>
2984 typename std::enable_if<Direction ==
2985 radix_tree<Key, Value, BytesView,
2986 MtMode>::node::direction::Reverse,
2987 typename radix_tree<Key, Value, BytesView, MtMode>::
2988 node::reverse_iterator>::type
2989 radix_tree<Key, Value, BytesView, MtMode>::node::begin()
const
2991 return reverse_iterator(end<direction::Forward>());
2994 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
2995 template <
bool Direction>
2996 typename std::enable_if<Direction ==
2997 radix_tree<Key, Value, BytesView,
2998 MtMode>::node::direction::Reverse,
2999 typename radix_tree<Key, Value, BytesView, MtMode>::
3000 node::reverse_iterator>::type
3001 radix_tree<Key, Value, BytesView, MtMode>::node::end()
const
3003 return reverse_iterator(begin<direction::Forward>());
3006 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3007 template <
bool Direction,
typename Ptr>
3008 typename radix_tree<Key, Value, BytesView,
3009 MtMode>::node::template iterator<Direction>
3010 radix_tree<Key, Value, BytesView, MtMode>::node::find_child(
const Ptr &n)
const
3012 auto it = begin<Direction>();
3013 while (it != end<Direction>()) {
3021 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3022 template <
bool Direction,
typename Enable>
3023 typename radix_tree<Key, Value, BytesView,
3024 MtMode>::node::template iterator<Direction>
3025 radix_tree<Key, Value, BytesView, MtMode>::node::make_iterator(
3026 const atomic_pointer_type *ptr)
const
3028 return forward_iterator(ptr,
this);
3031 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3032 template <
bool IsConst>
3033 radix_tree<Key, Value, BytesView, MtMode>::radix_tree_iterator<
3034 IsConst>::radix_tree_iterator(leaf_ptr leaf_, tree_ptr tree)
3035 : leaf_(leaf_), tree(tree)
3040 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3041 template <
bool IsConst>
3042 template <
bool C,
typename Enable>
3043 radix_tree<Key, Value, BytesView, MtMode>::radix_tree_iterator<
3044 IsConst>::radix_tree_iterator(
const radix_tree_iterator<false> &rhs)
3045 : leaf_(rhs.leaf_), tree(rhs.tree)
3050 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3051 template <
bool IsConst>
3052 typename radix_tree<Key, Value, BytesView,
3053 MtMode>::template radix_tree_iterator<IsConst>::reference
3054 radix_tree<Key, Value, BytesView,
3055 MtMode>::radix_tree_iterator<IsConst>::operator*()
const
3063 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3064 template <
bool IsConst>
3065 typename radix_tree<Key, Value, BytesView,
3066 MtMode>::template radix_tree_iterator<IsConst>::pointer
3067 radix_tree<Key, Value, BytesView,
3068 MtMode>::radix_tree_iterator<IsConst>::operator->()
const
3087 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3088 template <
bool IsConst>
3089 template <
typename V,
typename Enable>
3091 radix_tree<Key, Value, BytesView, MtMode>::radix_tree_iterator<
3092 IsConst>::assign_val(basic_string_view<
typename V::value_type,
3093 typename V::traits_type>
3099 auto pop = pool_base(pmemobj_pool_by_ptr(leaf_));
3101 if (rhs.size() <= leaf_->value().capacity() && !MtMode) {
3108 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3109 template <
bool IsConst>
3110 template <
typename T>
3112 radix_tree<Key, Value, BytesView,
3113 MtMode>::radix_tree_iterator<IsConst>::replace_val(T &&rhs)
3115 auto pop = pool_base(pmemobj_pool_by_ptr(leaf_));
3116 atomic_pointer_type *slot;
3118 if (!load(leaf_->parent)) {
3119 assert(get_leaf(load(tree->root)) == leaf_);
3122 slot =
const_cast<atomic_pointer_type *
>(
3123 &*load(leaf_->parent)->find_child(leaf_));
3126 auto old_leaf = leaf_;
3130 leaf::make_key_args(load(old_leaf->parent),
3132 std::forward<T>(rhs)));
3133 tree->free(persistent_ptr<radix_tree::leaf>(old_leaf));
3136 leaf_ = get_leaf(load(*slot));
3146 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3147 template <
bool IsConst>
3148 template <
typename T,
typename V,
typename Enable>
3150 radix_tree<Key, Value, BytesView,
3151 MtMode>::radix_tree_iterator<IsConst>::assign_val(T &&rhs)
3153 if (MtMode && tree->ebr_ !=
nullptr)
3154 replace_val(std::forward<T>(rhs));
3156 auto pop = pool_base(pmemobj_pool_by_ptr(leaf_));
3158 pop, [&] { leaf_->value() = std::forward<T>(rhs); });
3162 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3163 template <
bool IsConst>
3164 typename radix_tree<Key, Value, BytesView,
3165 MtMode>::template radix_tree_iterator<IsConst> &
3166 radix_tree<Key, Value, BytesView,
3167 MtMode>::radix_tree_iterator<IsConst>::operator++()
3170 if (!try_increment())
3171 *
this = tree->upper_bound(leaf_->key());
3180 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3181 template <
bool IsConst>
3183 radix_tree<Key, Value, BytesView,
3184 MtMode>::radix_tree_iterator<IsConst>::try_increment()
3189 constexpr
auto direction = radix_tree::node::direction::Forward;
3190 auto parent_ptr = load(leaf_->parent);
3196 auto it = parent_ptr->template find_child<direction>(leaf_);
3198 if (it == parent_ptr->template end<direction>())
3201 auto ret = tree->template next_leaf<direction>(it, parent_ptr);
3206 leaf_ =
const_cast<leaf_ptr
>(ret.second);
3218 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3219 template <
bool IsConst>
3220 template <
bool Mt,
typename Enable>
3221 typename radix_tree<Key, Value, BytesView,
3222 MtMode>::template radix_tree_iterator<IsConst> &
3223 radix_tree<Key, Value, BytesView,
3224 MtMode>::radix_tree_iterator<IsConst>::operator--()
3226 while (!try_decrement()) {
3227 *
this = tree->lower_bound(leaf_->key());
3237 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3238 template <
bool IsConst>
3240 radix_tree<Key, Value, BytesView,
3241 MtMode>::radix_tree_iterator<IsConst>::try_decrement()
3243 constexpr
auto direction = radix_tree::node::direction::Reverse;
3249 auto r = load(tree->root);
3254 leaf_ =
const_cast<leaf_ptr
>(
3255 tree->template find_leaf<direction>(r));
3260 auto parent_ptr = load(leaf_->parent);
3265 auto it = parent_ptr->template find_child<direction>(
3268 if (it == parent_ptr->template end<direction>())
3271 auto ret = tree->template next_leaf<direction>(
3277 leaf_ =
const_cast<leaf_ptr
>(ret.second);
3283 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3284 template <
bool IsConst>
3285 typename radix_tree<Key, Value, BytesView,
3286 MtMode>::template radix_tree_iterator<IsConst>
3287 radix_tree<Key, Value, BytesView,
3288 MtMode>::radix_tree_iterator<IsConst>::operator++(int)
3303 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3304 template <
bool IsConst>
3305 template <
bool Mt,
typename Enable>
3306 typename radix_tree<Key, Value, BytesView,
3307 MtMode>::template radix_tree_iterator<IsConst>
3308 radix_tree<Key, Value, BytesView,
3309 MtMode>::radix_tree_iterator<IsConst>::operator--(int)
3318 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3319 template <
bool IsConst>
3322 radix_tree<Key, Value, BytesView, MtMode>::radix_tree_iterator<
3323 IsConst>::operator!=(
const radix_tree_iterator<C> &rhs)
const
3325 return leaf_ != rhs.leaf_;
3328 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3329 template <
bool IsConst>
3332 radix_tree<Key, Value, BytesView, MtMode>::radix_tree_iterator<
3333 IsConst>::operator==(
const radix_tree_iterator<C> &rhs)
const
3335 return !(*
this != rhs);
3347 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3348 template <
bool Direction,
typename Iterator>
3350 const typename radix_tree<Key, Value, BytesView, MtMode>::leaf *>
3351 radix_tree<Key, Value, BytesView, MtMode>::next_leaf(Iterator node,
3352 pointer_type parent)
const
3358 if (node == parent->template end<Direction>()) {
3359 auto p = load(parent->parent);
3361 return {
true,
nullptr};
3363 auto p_it = p->template find_child<Direction>(parent);
3364 if (p_it == p->template end<Direction>()) {
3366 return {
false,
nullptr};
3369 return next_leaf<Direction>(p_it, p);
3372 auto n = load(*node);
3376 auto leaf = find_leaf<Direction>(n);
3378 return {
false,
nullptr};
3380 return {
true, leaf};
3391 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3392 template <
bool Direction>
3393 const typename radix_tree<Key, Value, BytesView, MtMode>::leaf *
3394 radix_tree<Key, Value, BytesView, MtMode>::find_leaf(
3395 typename radix_tree<Key, Value, BytesView, MtMode>::pointer_type n)
3403 for (
auto it = n->template begin<Direction>();
3404 it != n->template end<Direction>(); ++it) {
3405 auto ptr = load(*it);
3407 return find_leaf<Direction>(ptr);
3415 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3417 radix_tree<Key, Value, BytesView, MtMode>::leaf::key()
3419 auto &const_key =
const_cast<const leaf *
>(
this)->key();
3420 return *
const_cast<Key *
>(&const_key);
3423 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3425 radix_tree<Key, Value, BytesView, MtMode>::leaf::value()
3427 auto &const_value =
const_cast<const leaf *
>(
this)->value();
3428 return *
const_cast<Value *
>(&const_value);
3431 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3433 radix_tree<Key, Value, BytesView, MtMode>::leaf::key()
const
3435 return *
reinterpret_cast<const Key *
>(
this + 1);
3438 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3440 radix_tree<Key, Value, BytesView, MtMode>::leaf::value()
const
3442 auto key_dst =
reinterpret_cast<const char *
>(
this + 1);
3443 auto key_size = total_sizeof<Key>::value(key());
3444 auto padding = detail::align_up(key_size,
alignof(Value)) - key_size;
3446 reinterpret_cast<const Value *
>(key_dst + padding + key_size);
3451 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3452 radix_tree<Key, Value, BytesView, MtMode>::leaf::~leaf()
3454 detail::destroy<Key>(key());
3455 detail::destroy<Value>(value());
3458 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3459 persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
3460 radix_tree<Key, Value, BytesView, MtMode>::leaf::make(pointer_type parent)
3462 auto t = std::make_tuple();
3463 return make(parent, std::piecewise_construct, t, t,
3464 detail::index_sequence_for<>{},
3465 detail::index_sequence_for<>{});
3468 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3469 template <
typename... Args1,
typename... Args2>
3470 persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
3471 radix_tree<Key, Value, BytesView, MtMode>::leaf::make(
3472 pointer_type parent, std::piecewise_construct_t pc,
3473 std::tuple<Args1...> first_args, std::tuple<Args2...> second_args)
3475 return make(parent, pc, first_args, second_args,
3476 detail::index_sequence_for<Args1...>{},
3477 detail::index_sequence_for<Args2...>{});
3480 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3481 persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
3482 radix_tree<Key, Value, BytesView, MtMode>::leaf::make(pointer_type parent,
3486 return make(parent, std::piecewise_construct, std::forward_as_tuple(k),
3487 std::forward_as_tuple(v));
3490 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3491 template <
typename K,
typename V>
3492 persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
3493 radix_tree<Key, Value, BytesView, MtMode>::leaf::make(pointer_type parent,
3496 return make(parent, std::piecewise_construct,
3497 std::forward_as_tuple(std::forward<K>(k)),
3498 std::forward_as_tuple(std::forward<V>(v)));
3501 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3502 template <
typename K,
typename... Args>
3503 persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
3504 radix_tree<Key, Value, BytesView, MtMode>::leaf::make_key_args(
3505 pointer_type parent, K &&k, Args &&... args)
3507 return make(parent, std::piecewise_construct,
3508 std::forward_as_tuple(std::forward<K>(k)),
3509 std::forward_as_tuple(std::forward<Args>(args)...));
3512 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3513 template <
typename K,
typename V>
3514 persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
3515 radix_tree<Key, Value, BytesView, MtMode>::leaf::make(pointer_type parent,
3516 detail::pair<K, V> &&p)
3518 return make(parent, std::piecewise_construct,
3519 std::forward_as_tuple(std::move(p.first)),
3520 std::forward_as_tuple(std::move(p.second)));
3523 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3524 template <
typename K,
typename V>
3525 persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
3526 radix_tree<Key, Value, BytesView, MtMode>::leaf::make(
3527 pointer_type parent,
const detail::pair<K, V> &p)
3529 return make(parent, std::piecewise_construct,
3530 std::forward_as_tuple(p.first),
3531 std::forward_as_tuple(p.second));
3534 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3535 template <
typename K,
typename V>
3536 persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
3537 radix_tree<Key, Value, BytesView, MtMode>::leaf::make(pointer_type parent,
3538 std::pair<K, V> &&p)
3540 return make(parent, std::piecewise_construct,
3541 std::forward_as_tuple(std::move(p.first)),
3542 std::forward_as_tuple(std::move(p.second)));
3545 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3546 template <
typename K,
typename V>
3547 persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
3548 radix_tree<Key, Value, BytesView, MtMode>::leaf::make(pointer_type parent,
3549 const std::pair<K, V> &p)
3551 return make(parent, std::piecewise_construct,
3552 std::forward_as_tuple(p.first),
3553 std::forward_as_tuple(p.second));
3556 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3557 template <
typename... Args1,
typename... Args2,
size_t... I1,
size_t... I2>
3558 persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
3559 radix_tree<Key, Value, BytesView, MtMode>::leaf::make(
3560 pointer_type parent, std::piecewise_construct_t,
3561 std::tuple<Args1...> &first_args, std::tuple<Args2...> &second_args,
3562 detail::index_sequence<I1...>, detail::index_sequence<I2...>)
3564 standard_alloc_policy<void> a;
3565 auto key_size = total_sizeof<Key>::value(std::get<I1>(first_args)...);
3567 total_sizeof<Value>::value(std::get<I2>(second_args)...);
3568 auto padding = detail::align_up(key_size,
alignof(Value)) - key_size;
3569 auto ptr =
static_cast<persistent_ptr<leaf>
>(
3570 a.allocate(
sizeof(leaf) + key_size + padding + val_size));
3572 auto key_dst =
reinterpret_cast<Key *
>(ptr.
get() + 1);
3573 auto val_dst =
reinterpret_cast<Value *
>(
3574 reinterpret_cast<char *
>(key_dst) + padding + key_size);
3576 assert(
reinterpret_cast<uintptr_t
>(key_dst) %
alignof(Key) == 0);
3577 assert(
reinterpret_cast<uintptr_t
>(val_dst) %
alignof(Value) == 0);
3579 new (ptr.
get()) leaf();
3580 new (key_dst) Key(std::forward<Args1>(std::get<I1>(first_args))...);
3581 new (val_dst) Value(std::forward<Args2>(std::get<I2>(second_args))...);
3583 store(ptr->parent, parent);
3588 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3589 persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
3590 radix_tree<Key, Value, BytesView, MtMode>::leaf::make(pointer_type parent,
3593 return make(parent, other.key(), other.value());
3602 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3604 radix_tree<Key, Value, BytesView, MtMode>::check_pmem()
3606 if (
nullptr == pmemobj_pool_by_ptr(
this))
3617 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3619 radix_tree<Key, Value, BytesView, MtMode>::check_tx_stage_work()
3621 if (pmemobj_tx_stage() != TX_STAGE_WORK)
3623 "Function called out of transaction scope.");
3626 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3628 radix_tree<Key, Value, BytesView, MtMode>::is_leaf(
3629 const radix_tree<Key, Value, BytesView, MtMode>::pointer_type &p)
3631 return p.template is<leaf>();
3634 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3635 typename radix_tree<Key, Value, BytesView, MtMode>::leaf *
3636 radix_tree<Key, Value, BytesView, MtMode>::get_leaf(
3637 const radix_tree<Key, Value, BytesView, MtMode>::pointer_type &p)
3639 return p.template get<leaf>();
3642 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3643 typename radix_tree<Key, Value, BytesView, MtMode>::node *
3644 radix_tree<Key, Value, BytesView, MtMode>::get_node(
3645 const radix_tree<Key, Value, BytesView, MtMode>::pointer_type &p)
3647 return p.template get<node>();
3654 template <
typename Key,
typename Value,
typename BytesView,
bool MtMode>
3665 struct is_string : std::false_type {
3668 template <
typename CharT,
typename Traits>
3669 struct is_string<obj::
basic_string<CharT, Traits>> : std::true_type {
3672 template <
typename CharT,
typename Traits>
3673 struct is_string<obj::experimental::basic_inline_string<CharT, Traits>>
3677 template <
typename T>
3678 struct bytes_view<T, typename std::enable_if<is_string<T>::value>::type> {
3679 using CharT =
typename T::value_type;
3680 using Traits =
typename T::traits_type;
3684 typename Enable =
typename std::enable_if<std::is_constructible<
3685 obj::basic_string_view<CharT, Traits>, C>::value>::type>
3686 bytes_view(
const C *s) : s(*s)
3690 char operator[](std::size_t p)
const
3692 return reinterpret_cast<const char *
>(s.data())[p];
3698 return s.size() *
sizeof(CharT);
3701 obj::basic_string_view<CharT, Traits> s;
3703 using is_transparent = void;
3706 template <
typename T>
3707 struct bytes_view<T,
3708 typename std::enable_if<std::is_integral<T>::value &&
3709 !std::is_signed<T>::value>::type> {
3710 bytes_view(
const T *k) : k(k)
3712 #if __cpp_lib_endian
3714 std::endian::native == std::endian::little,
3715 "Scalar type are not little endian on this platform!");
3716 #elif !defined(NDEBUG)
3718 uint16_t word = (2 << 8) + 1;
3719 assert(((
char *)&word)[0] == 1);
3723 char operator[](std::size_t p)
const
3725 return reinterpret_cast<const char *
>(k)[size() - p - 1];
Persistent memory aware allocator.
Epoch-based reclamation (EBR).
Definition: ebr.hpp:68
Our partial std::string_view implementation.
Definition: string_view.hpp:48
Persistent string container with std::basic_string compatible interface.
Definition: basic_string.hpp:48
static void run(obj::pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:676
Persistent associative, ordered container with API similar and partially compatible with the API of s...
Definition: radix_tree.hpp:123
const_reverse_iterator crend() const
Returns a const, reverse iterator to the end.
Definition: radix_tree.hpp:2765
const_iterator cbegin() const
Returns a const iterator to the first element of the container.
Definition: radix_tree.hpp:2656
void runtime_finalize_mt()
If MtMode == true, this function must be called before each application close and before calling radi...
Definition: radix_tree.hpp:1106
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition: radix_tree.hpp:2736
void swap(radix_tree &rhs)
Member swap.
Definition: radix_tree.hpp:976
iterator begin()
Returns an iterator to the first element of the container.
Definition: radix_tree.hpp:2624
const_reverse_iterator crbegin() const
Returns a const, reverse iterator to the beginning.
Definition: radix_tree.hpp:2750
uint64_t size() const noexcept
Definition: radix_tree.hpp:964
iterator end()
Returns an iterator to the element following the last element of the map.
Definition: radix_tree.hpp:2641
void swap(radix_tree< Key, Value, BytesView, MtMode > &lhs, radix_tree< Key, Value, BytesView, MtMode > &rhs)
Non-member swap.
Definition: radix_tree.hpp:3656
void runtime_initialize_mt(ebr *e=new ebr())
If MtMode == true, this function must be called after each application restart.
Definition: radix_tree.hpp:1091
bool empty() const noexcept
Checks whether the container is empty.
Definition: radix_tree.hpp:944
size_type max_size() const noexcept
Definition: radix_tree.hpp:954
std::pair< iterator, bool > insert(const value_type &v)
Inserts element if the tree doesn't already contain an element with an equivalent key.
Definition: radix_tree.hpp:1614
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition: radix_tree.hpp:2721
iterator erase(const_iterator pos)
Removes the element at pos from the container.
Definition: radix_tree.hpp:2048
worker_type register_worker()
Registers and returns a new worker, which can perform critical operations (accessing some shared data...
Definition: radix_tree.hpp:1125
iterator lower_bound(const key_type &k)
Returns an iterator pointing to the first element that is not less than (i.e.
Definition: radix_tree.hpp:2485
~radix_tree()
Destructor.
Definition: radix_tree.hpp:926
void clear()
Erases all elements from the container transactionally.
Definition: radix_tree.hpp:2025
iterator find(const key_type &k)
Finds an element with key equivalent to key.
Definition: radix_tree.hpp:1932
void garbage_collect()
Tries to collect and free some garbage produced by erase, clear, insert_or_assign or assign_val in co...
Definition: radix_tree.hpp:1019
radix_tree & operator=(const radix_tree &m)
Copy assignment operator.
Definition: radix_tree.hpp:839
iterator upper_bound(const key_type &k)
Returns an iterator pointing to the first element that is greater than key.
Definition: radix_tree.hpp:2565
void garbage_collect_force()
Performs full epochs synchronisation.
Definition: radix_tree.hpp:998
const_iterator cend() const
Returns a const iterator to the element following the last element of the map.
Definition: radix_tree.hpp:2680
size_type count(const key_type &k) const
Returns the number of elements with key that compares equivalent to the specified argument.
Definition: radix_tree.hpp:1897
radix_tree()
Default radix tree constructor.
Definition: radix_tree.hpp:718
Volatile residing on pmem class.
Definition: v.hpp:43
static void run(obj::pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:810
Resides on pmem class.
Definition: p.hpp:36
Persistent pointer class.
Definition: persistent_ptr.hpp:153
element_type * get() const noexcept
Get the direct pointer.
Definition: persistent_ptr.hpp:479
The non-template pool base class.
Definition: pool.hpp:51
Custom pool error class.
Definition: pexceptions.hpp:84
Custom transaction error class.
Definition: pexceptions.hpp:167
Commonly used functionality.
C++ Epoch-based reclamation API.
basic_string_view< char > string_view
The most typical string_view usage - the char specialization.
Definition: string_view.hpp:169
Inline string implementation.
Create c++14 style index sequence.
persistent_ptr transactional allocation functions for objects.
static uint8_t mssb_index(unsigned int value)
Returns index of most significant set bit.
Definition: common.hpp:289
std::ostream & operator<<(std::ostream &os, const radix_tree< K, V, BV, MtMode > &tree)
Prints tree in DOT format.
Definition: radix_tree.hpp:2843
pool_base pool_by_vptr(const T *that)
Retrieve pool handle for the given pointer.
Definition: utils.hpp:32
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Resides on pmem property template.
Persistent smart pointer.
Convenience extensions for the resides on pmem property template.
Persistent self-relative smart pointer.
String typedefs for common character types.
Our partial std::string_view implementation.
This is the structure which 'holds' key/value pair.
Definition: radix_tree.hpp:438
This is internal node.
Definition: radix_tree.hpp:504
atomic_pointer_type parent
Pointer to a parent node.
Definition: radix_tree.hpp:510
byten_t byte
Byte and bit together are used to calculate the NIB which is used to index the child array.
Definition: radix_tree.hpp:533
atomic_pointer_type embedded_entry
The embedded_entry ptr is used only for nodes for which length of the path from root is a multiple of...
Definition: radix_tree.hpp:518
Persistent tagged pointer.
Commonly used SFINAE helpers.
C++ pmemobj transactions.
Volatile residing on pmem property template.