16 #ifndef LIBPMEMOBJ_CPP_RADIX_HPP
17 #define LIBPMEMOBJ_CPP_RADIX_HPP
21 #include <libpmemobj++/detail/pair.hpp>
49 template <
typename T,
typename Enable =
void>
56 namespace experimental
101 template <
typename Key,
typename Value,
102 typename BytesView = detail::bytes_view<Key>>
104 template <
bool IsConst>
108 using key_type = Key;
109 using mapped_type = Value;
110 using value_type = detail::pair<const key_type, mapped_type>;
111 using size_type = std::size_t;
112 using reference = value_type &;
113 using const_reference =
const value_type &;
116 using reverse_iterator = std::reverse_iterator<iterator>;
117 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
118 using difference_type = std::ptrdiff_t;
122 template <
class InputIt>
126 radix_tree(std::initializer_list<value_type> il);
134 template <
class... Args>
135 std::pair<iterator, bool> emplace(Args &&... args);
137 std::pair<iterator, bool>
insert(
const value_type &
v);
138 std::pair<iterator, bool>
insert(value_type &&
v);
139 template <
typename P,
140 typename =
typename std::enable_if<
141 std::is_constructible<value_type, P &&>::value,
143 std::pair<iterator, bool>
insert(P &&
p);
151 template <
class InputIterator>
152 void insert(InputIterator first, InputIterator last);
153 void insert(std::initializer_list<value_type> il);
157 template <
class... Args>
158 std::pair<iterator, bool> try_emplace(
const key_type &k,
160 template <
class... Args>
161 std::pair<iterator, bool> try_emplace(key_type &&k, Args &&... args);
169 template <
typename K,
typename BV = BytesView,
class... Args>
170 auto try_emplace(K &&k, Args &&... args) ->
typename std::enable_if<
171 detail::has_is_transparent<BV>::value &&
172 !std::is_same<typename std::remove_reference<K>::type,
174 std::pair<iterator, bool>>::type;
176 template <
typename M>
177 std::pair<iterator, bool> insert_or_assign(
const key_type &k, M &&obj);
178 template <
typename M>
179 std::pair<iterator, bool> insert_or_assign(key_type &&k, M &&obj);
186 typename M,
typename K,
187 typename =
typename std::enable_if<
188 detail::has_is_transparent<BytesView>::value, K>::type>
189 std::pair<iterator, bool> insert_or_assign(K &&k, M &&obj);
193 size_type
erase(
const key_type &k);
194 template <
typename K,
195 typename =
typename std::enable_if<
196 detail::has_is_transparent<BytesView>::value &&
197 !std::is_same<K, iterator>::value &&
198 !std::is_same<K, const_iterator>::value,
200 size_type
erase(
const K &k);
204 size_type
count(
const key_type &k)
const;
207 typename =
typename std::enable_if<
208 detail::has_is_transparent<BytesView>::value, K>::type>
209 size_type
count(
const K &k)
const;
215 typename =
typename std::enable_if<
216 detail::has_is_transparent<BytesView>::value, K>::type>
220 typename =
typename std::enable_if<
221 detail::has_is_transparent<BytesView>::value, K>::type>
228 typename =
typename std::enable_if<
229 detail::has_is_transparent<BytesView>::value, K>::type>
233 typename =
typename std::enable_if<
234 detail::has_is_transparent<BytesView>::value, K>::type>
241 typename =
typename std::enable_if<
242 detail::has_is_transparent<BytesView>::value, K>::type>
246 typename =
typename std::enable_if<
247 detail::has_is_transparent<BytesView>::value, K>::type>
257 reverse_iterator
rbegin();
258 reverse_iterator
rend();
259 const_reverse_iterator
crbegin()
const;
260 const_reverse_iterator
crend()
const;
261 const_reverse_iterator
rbegin()
const;
262 const_reverse_iterator
rend()
const;
265 bool empty()
const noexcept;
266 size_type
max_size()
const noexcept;
267 uint64_t
size()
const noexcept;
271 template <
typename K,
typename V,
typename BV>
272 friend std::ostream &
operator<<(std::ostream &os,
276 using byten_t = uint64_t;
277 using bitn_t = uint8_t;
280 static constexpr std::size_t SLICE = 4;
282 static constexpr std::size_t NIB = ((1ULL << SLICE) - 1);
284 static constexpr std::size_t SLNODES = (1 << SLICE);
286 static constexpr bitn_t SLICE_MASK = (bitn_t) ~(SLICE - 1);
288 static constexpr bitn_t FIRST_NIB = 8 - SLICE;
290 struct tagged_node_ptr;
295 tagged_node_ptr root;
299 template <
typename K,
typename F,
class... Args>
300 std::pair<iterator, bool> internal_emplace(
const K &, F &&);
301 template <
typename K>
302 leaf *internal_find(
const K &k)
const;
304 static tagged_node_ptr &parent_ref(tagged_node_ptr n);
305 template <
typename K1,
typename K2>
306 static bool keys_equal(
const K1 &k1,
const K2 &k2);
307 template <
typename K1,
typename K2>
308 static int compare(
const K1 &k1,
const K2 &k2, byten_t offset = 0);
309 template <
bool Direction,
typename Iterator>
310 static leaf *next_leaf(Iterator child, tagged_node_ptr parent);
311 template <
bool Direction>
312 static leaf *find_leaf(tagged_node_ptr n);
313 static unsigned slice_index(
char k, uint8_t shift);
314 template <
typename K1,
typename K2>
315 static byten_t prefix_diff(
const K1 &lhs,
const K2 &rhs,
317 leaf *any_leftmost_leaf(tagged_node_ptr n, size_type min_depth)
const;
318 template <
typename K1,
typename K2>
319 static bitn_t bit_diff(
const K1 &leaf_key,
const K2 &key, byten_t diff);
320 template <
typename K>
321 leaf *common_prefix_leaf(
const K &key)
const;
322 static void print_rec(std::ostream &os, radix_tree::tagged_node_ptr n);
323 template <
typename K>
324 static BytesView bytes_view(
const K &k);
326 static bool path_length_equal(
size_t key_size, tagged_node_ptr n);
327 template <
typename K>
328 std::tuple<const tagged_node_ptr *, tagged_node_ptr>
329 descend(
const K &k, byten_t diff, bitn_t sh)
const;
330 template <
typename K>
331 std::tuple<tagged_node_ptr *, tagged_node_ptr>
332 descend(
const K &k, byten_t diff, bitn_t sh);
333 template <
bool Lower,
typename K>
339 static_assert(
sizeof(
node) == 256,
340 "Internal node should have size equal to 256 bytes.");
343 template <
typename Key,
typename Value,
typename BytesView>
347 template <
typename Key,
typename Value,
typename BytesView>
348 struct radix_tree<Key, Value, BytesView>::tagged_node_ptr {
349 tagged_node_ptr() =
default;
350 tagged_node_ptr(
const tagged_node_ptr &rhs) =
default;
352 tagged_node_ptr(std::nullptr_t);
356 tagged_node_ptr &
operator=(
const tagged_node_ptr &rhs) =
default;
358 tagged_node_ptr &
operator=(std::nullptr_t);
362 bool operator==(
const tagged_node_ptr &rhs)
const;
363 bool operator!=(
const tagged_node_ptr &rhs)
const;
368 void swap(tagged_node_ptr &rhs);
370 bool is_leaf()
const;
377 explicit operator
bool() const noexcept;
380 static constexpr uintptr_t IS_LEAF = 1;
382 void *remove_tag(
void *ptr) const;
396 template <typename Key, typename Value, typename BytesView>
411 const Key &key()
const;
412 const Value &value()
const;
416 template <
typename... Args1,
typename... Args2>
418 make(tagged_node_ptr parent, std::piecewise_construct_t pc,
419 std::tuple<Args1...> first_args, std::tuple<Args2...> second_args);
420 template <
typename K,
typename V>
424 template <
typename K,
typename... Args>
427 template <
typename K,
typename V>
429 detail::pair<K, V> &&
p);
430 template <
typename K,
typename V>
432 const detail::pair<K, V> &
p);
433 template <
typename K,
typename V>
435 std::pair<K, V> &&
p);
436 template <
typename K,
typename V>
438 const std::pair<K, V> &
p);
443 friend class radix_tree<Key, Value, BytesView>;
447 template <
typename... Args1,
typename... Args2,
size_t... I1,
450 make(tagged_node_ptr parent, std::piecewise_construct_t,
451 std::tuple<Args1...> &first_args,
452 std::tuple<Args2...> &second_args, detail::index_sequence<I1...>,
453 detail::index_sequence<I2...>);
455 tagged_node_ptr parent =
nullptr;
462 template <
typename Key,
typename Value,
typename BytesView>
464 node(tagged_node_ptr parent, byten_t
byte, bitn_t bit);
480 tagged_node_ptr child[SLNODES];
496 static constexpr
bool Forward = 0;
497 static constexpr
bool Reverse = 1;
500 struct forward_iterator;
501 using reverse_iterator = std::reverse_iterator<forward_iterator>;
503 template <
bool Direction>
505 typename std::conditional<Direction == direction::Forward,
507 reverse_iterator>::type;
509 template <
bool Direction = direction::Forward>
510 typename std::enable_if<
513 BytesView>::node::direction::Forward,
515 BytesView>::node::forward_iterator>::type
518 template <
bool Direction = direction::Forward>
519 typename std::enable_if<
522 BytesView>::node::direction::Forward,
524 BytesView>::node::forward_iterator>::type
528 template <
bool Direction = direction::Forward>
529 typename std::enable_if<
532 BytesView>::node::direction::Reverse,
534 BytesView>::node::reverse_iterator>::type
538 template <
bool Direction = direction::Forward>
539 typename std::enable_if<
542 BytesView>::node::direction::Reverse,
544 BytesView>::node::reverse_iterator>::type
547 template <
bool Direction = direction::Forward,
typename Ptr>
550 template <
bool Direction = direction::Forward,
551 typename Enable =
typename std::enable_if<
552 Direction == direction::Forward>::type>
555 uint8_t padding[256 -
sizeof(parent) -
sizeof(
leaf) -
sizeof(child) -
556 sizeof(
byte) -
sizeof(bit)];
564 template <
typename Key,
typename Value,
typename BytesView>
565 template <
bool IsConst>
569 typename std::conditional<IsConst, const leaf *, leaf *>::type;
571 typename std::conditional<IsConst,
const tagged_node_ptr *,
572 tagged_node_ptr *>::type;
576 using difference_type = std::ptrdiff_t;
578 using reference =
typename std::conditional<IsConst,
const value_type &,
580 using pointer =
typename std::conditional<IsConst,
value_type const *,
582 using iterator_category = std::bidirectional_iterator_tag;
588 template <
bool C = IsConst,
589 typename Enable =
typename std::enable_if<C>::type>
595 reference operator*()
const;
596 pointer operator->()
const;
598 template <
typename V = Value,
599 typename Enable =
typename std::enable_if<
600 detail::is_inline_string<V>::value>::type>
602 typename V::traits_type>
605 template <
typename T,
typename V = Value,
606 typename Enable =
typename std::enable_if<
607 !detail::is_inline_string<V>::value>::type>
608 void assign_val(T &&rhs);
625 leaf_ptr leaf_ =
nullptr;
626 node_ptr root =
nullptr;
629 template <
typename Key,
typename Value,
typename BytesView>
630 struct radix_tree<Key, Value, BytesView>::node::forward_iterator {
631 using difference_type = std::ptrdiff_t;
632 using value_type = tagged_node_ptr;
633 using pointer =
const value_type *;
634 using reference =
const value_type &;
635 using iterator_category = std::forward_iterator_tag;
637 forward_iterator(pointer child,
const node *
node);
644 reference operator*()
const;
645 pointer operator->()
const;
647 pointer get_node()
const;
649 bool operator!=(
const forward_iterator &rhs)
const;
650 bool operator==(
const forward_iterator &rhs)
const;
665 template <
typename Key,
typename Value,
typename BytesView>
691 template <
typename Key,
typename Value,
typename BytesView>
692 template <
class InputIt>
694 : root(nullptr), size_(0)
699 for (
auto it = first; it != last; it++)
718 template <
typename Key,
typename Value,
typename BytesView>
722 check_tx_stage_work();
727 for (
auto it = m.
cbegin(); it != m.
cend(); it++)
743 template <
typename Key,
typename Value,
typename BytesView>
747 check_tx_stage_work();
769 template <
typename Key,
typename Value,
typename BytesView>
771 std::initializer_list<value_type> il)
785 template <
typename Key,
typename Value,
typename BytesView>
793 if (
this != &other) {
797 this->root =
nullptr;
800 for (
auto it = other.
cbegin(); it != other.
cend(); it++)
816 template <
typename Key,
typename Value,
typename BytesView>
824 if (
this != &other) {
828 this->root = other.root;
829 this->size_ = other.size_;
830 other.root =
nullptr;
848 template <
typename Key,
typename Value,
typename BytesView>
851 std::initializer_list<value_type> ilist)
860 this->root =
nullptr;
863 for (
auto it = ilist.begin(); it != ilist.end(); it++)
873 template <
typename Key,
typename Value,
typename BytesView>
888 template <
typename Key,
typename Value,
typename BytesView>
898 template <
typename Key,
typename Value,
typename BytesView>
899 typename radix_tree<Key, Value, BytesView>::size_type
902 return std::numeric_limits<difference_type>::max();
908 template <
typename Key,
typename Value,
typename BytesView>
920 template <
typename Key,
typename Value,
typename BytesView>
927 this->size_.swap(rhs.size_);
928 this->root.swap(rhs.root);
935 template <
typename Key,
typename Value,
typename BytesView>
940 return n.get_leaf()->parent;
951 template <
typename Key,
typename Value,
typename BytesView>
952 typename radix_tree<Key, Value, BytesView>::leaf *
953 radix_tree<Key, Value, BytesView>::any_leftmost_leaf(
954 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr n,
955 size_type min_depth)
const
959 while (!n.is_leaf()) {
960 if (n->embedded_entry && n->byte >= min_depth)
961 return n->embedded_entry.get_leaf();
963 for (
size_t i = 0; i < SLNODES; i++) {
965 if ((m = n->child[i])) {
978 template <
typename Key,
typename Value,
typename BytesView>
979 template <
typename K>
980 typename radix_tree<Key, Value, BytesView>::leaf *
981 radix_tree<Key, Value, BytesView>::common_prefix_leaf(
const K &key)
const
985 while (n && !n.is_leaf() && n->byte < key.size()) {
986 auto nn = n->child[slice_index(key[n->byte], n->bit)];
991 n = any_leftmost_leaf(n, key.size());
999 n = any_leftmost_leaf(n, key.size());
1001 return n.get_leaf();
1004 template <
typename Key,
typename Value,
typename BytesView>
1005 template <
typename K>
1007 radix_tree<Key, Value, BytesView>::bytes_view(
const K &key)
1012 return BytesView(&key);
1015 template <
typename Key,
typename Value,
typename BytesView>
1017 radix_tree<Key, Value, BytesView>::bytes_view(string_view key)
1025 template <
typename Key,
typename Value,
typename BytesView>
1026 template <
typename K1,
typename K2>
1028 radix_tree<Key, Value, BytesView>::keys_equal(
const K1 &k1,
const K2 &k2)
1030 return k1.size() == k2.size() && compare(k1, k2) == 0;
1036 template <
typename Key,
typename Value,
typename BytesView>
1037 template <
typename K1,
typename K2>
1039 radix_tree<Key, Value, BytesView>::compare(
const K1 &k1,
const K2 &k2,
1042 auto ret = prefix_diff(k1, k2, offset);
1044 if (ret != (std::min)(k1.size(), k2.size()))
1045 return (
unsigned char)(k1[ret]) - (
unsigned char)(k2[ret]);
1047 return k1.size() - k2.size();
1053 template <
typename Key,
typename Value,
typename BytesView>
1054 template <
typename K1,
typename K2>
1055 typename radix_tree<Key, Value, BytesView>::byten_t
1056 radix_tree<Key, Value, BytesView>::prefix_diff(
const K1 &lhs,
const K2 &rhs,
1060 for (diff = offset; diff < (std::min)(lhs.size(), rhs.size()); diff++) {
1061 if (lhs[diff] != rhs[diff])
1072 template <
typename Key,
typename Value,
typename BytesView>
1074 radix_tree<Key, Value, BytesView>::path_length_equal(
size_t key_size,
1077 return n->byte == key_size && n->bit == bitn_t(FIRST_NIB);
1080 template <
typename Key,
typename Value,
typename BytesView>
1081 template <
typename K1,
typename K2>
1082 typename radix_tree<Key, Value, BytesView>::bitn_t
1083 radix_tree<Key, Value, BytesView>::bit_diff(
const K1 &leaf_key,
const K2 &key,
1086 auto min_key_len = (std::min)(leaf_key.size(), key.size());
1092 if (diff < min_key_len) {
1094 static_cast<unsigned char>(leaf_key[diff] ^ key[diff]);
1095 sh = pmem::detail::mssb_index((uint32_t)at) & SLICE_MASK;
1101 template <
typename Key,
typename Value,
typename BytesView>
1102 template <
typename K>
1103 std::tuple<const typename radix_tree<Key, Value, BytesView>::tagged_node_ptr *,
1104 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr>
1105 radix_tree<Key, Value, BytesView>::descend(
const K &key, byten_t diff,
1112 while (n && !n.is_leaf() &&
1113 (n->byte < diff || (n->byte == diff && n->bit >= sh))) {
1115 slot = &n->child[slice_index(key[n->byte], n->bit)];
1119 return {slot, prev};
1122 template <
typename Key,
typename Value,
typename BytesView>
1123 template <
typename K>
1124 std::tuple<typename radix_tree<Key, Value, BytesView>::tagged_node_ptr *,
1125 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr>
1126 radix_tree<Key, Value, BytesView>::descend(
const K &key, byten_t diff,
1129 const tagged_node_ptr *slot;
1130 tagged_node_ptr prev;
1132 std::tie(slot, prev) =
1133 const_cast<const radix_tree *
>(
this)->descend(key, diff, sh);
1135 return {
const_cast<tagged_node_ptr *
>(slot), prev};
1138 template <
typename Key,
typename Value,
typename BytesView>
1139 template <
typename K,
typename F,
class... Args>
1140 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1141 radix_tree<Key, Value, BytesView>::internal_emplace(
const K &k, F &&make_leaf)
1143 auto key = bytes_view(k);
1144 auto pop = pool_base(pmemobj_pool_by_ptr(
this));
1148 return {iterator(root.get_leaf(), &root),
true};
1158 auto leaf = common_prefix_leaf(key);
1159 auto leaf_key = bytes_view(leaf->key());
1160 auto diff = prefix_diff(key, leaf_key);
1161 auto sh = bit_diff(leaf_key, key, diff);
1164 if (diff == key.size() && leaf_key.size() == key.size())
1165 return {iterator(leaf, &root),
false};
1168 tagged_node_ptr *slot;
1169 tagged_node_ptr prev;
1170 std::tie(slot, prev) = descend(key, diff, sh);
1180 assert(diff < (std::min)(leaf_key.size(), key.size()));
1183 return {iterator(slot->get_leaf(), &root),
true};
1188 if (diff == key.size()) {
1189 if (!n.is_leaf() && path_length_equal(key.size(), n)) {
1190 assert(!n->embedded_entry);
1193 pop, [&] { n->embedded_entry = make_leaf(n); });
1195 return {iterator(n->embedded_entry.get_leaf(), &root),
1201 tagged_node_ptr node;
1203 node = make_persistent<radix_tree::node>(
1204 parent_ref(n), diff, bitn_t(FIRST_NIB));
1205 node->embedded_entry = make_leaf(node);
1206 node->child[slice_index(leaf_key[diff],
1207 bitn_t(FIRST_NIB))] = n;
1209 parent_ref(n) = node;
1213 return {iterator(node->embedded_entry.get_leaf(), &root),
true};
1216 if (diff == leaf_key.size()) {
1219 tagged_node_ptr node;
1223 node = make_persistent<radix_tree::node>(
1224 parent_ref(n), diff, bitn_t(FIRST_NIB));
1225 node->embedded_entry = n;
1226 node->child[slice_index(key[diff], bitn_t(FIRST_NIB))] =
1229 parent_ref(n) = node;
1233 return {iterator(node->child[slice_index(key[diff],
1244 tagged_node_ptr node;
1246 node = make_persistent<radix_tree::node>(parent_ref(n), diff,
1248 node->child[slice_index(leaf_key[diff], sh)] = n;
1249 node->child[slice_index(key[diff], sh)] = make_leaf(node);
1251 parent_ref(n) = node;
1255 return {iterator(node->child[slice_index(key[diff], sh)].get_leaf(),
1288 template <
typename Key,
typename Value,
typename BytesView>
1289 template <
class... Args>
1290 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1294 return internal_emplace(k, [&](tagged_node_ptr parent) {
1296 return leaf::make_key_args(parent, k,
1297 std::forward<Args>(args)...);
1327 template <
typename Key,
typename Value,
typename BytesView>
1328 template <
class... Args>
1329 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1332 auto pop =
pool_base(pmemobj_pool_by_ptr(
this));
1333 std::pair<iterator, bool> ret;
1336 auto leaf_ = leaf::make(
nullptr, std::forward<Args>(args)...);
1337 auto make_leaf = [&](tagged_node_ptr parent) {
1338 leaf_->parent = parent;
1343 ret = internal_emplace(leaf_->key(), make_leaf);
1346 delete_persistent<leaf>(leaf_);
1367 template <
typename Key,
typename Value,
typename BytesView>
1368 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1389 template <
typename Key,
typename Value,
typename BytesView>
1390 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1393 return emplace(std::move(
v));
1415 template <
typename Key,
typename Value,
typename BytesView>
1416 template <
typename P,
typename>
1417 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1420 return emplace(std::forward<P>(
p));
1434 template <
typename Key,
typename Value,
typename BytesView>
1435 template <
typename InputIterator>
1440 for (
auto it = first; it != last; it++)
1454 template <
typename Key,
typename Value,
typename BytesView>
1458 insert(il.begin(), il.end());
1485 template <
typename Key,
typename Value,
typename BytesView>
1486 template <
class... Args>
1487 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1490 return internal_emplace(k, [&](tagged_node_ptr parent) {
1492 return leaf::make_key_args(parent, std::move(k),
1493 std::forward<Args>(args)...);
1525 template <
typename Key,
typename Value,
typename BytesView>
1526 template <
typename K,
typename BV,
class... Args>
1529 typename std::enable_if<
1530 detail::has_is_transparent<BV>::value &&
1531 !std::is_same<typename std::remove_reference<K>::type,
1533 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
1537 return internal_emplace(k, [&](tagged_node_ptr parent) {
1539 return leaf::make_key_args(parent, std::forward<K>(k),
1540 std::forward<Args>(args)...);
1562 template <
typename Key,
typename Value,
typename BytesView>
1563 template <
typename M>
1564 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1567 auto ret = try_emplace(k, std::forward<M>(obj));
1569 ret.first.assign_val(std::forward<M>(obj));
1591 template <
typename Key,
typename Value,
typename BytesView>
1592 template <
typename M>
1593 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1596 auto ret = try_emplace(std::move(k), std::forward<M>(obj));
1598 ret.first.assign_val(std::forward<M>(obj));
1623 template <
typename Key,
typename Value,
typename BytesView>
1624 template <
typename M,
typename K,
typename>
1625 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1628 auto ret = try_emplace(std::forward<K>(k), std::forward<M>(obj));
1630 ret.first.assign_val(std::forward<M>(obj));
1643 template <
typename Key,
typename Value,
typename BytesView>
1644 typename radix_tree<Key, Value, BytesView>::size_type
1647 return internal_find(k) !=
nullptr ? 1 : 0;
1662 template <
typename Key,
typename Value,
typename BytesView>
1663 template <
typename K,
typename>
1664 typename radix_tree<Key, Value, BytesView>::size_type
1667 return internal_find(k) !=
nullptr ? 1 : 0;
1678 template <
typename Key,
typename Value,
typename BytesView>
1682 return iterator(internal_find(k), &root);
1693 template <
typename Key,
typename Value,
typename BytesView>
1711 template <
typename Key,
typename Value,
typename BytesView>
1712 template <
typename K,
typename>
1716 return iterator(internal_find(k), &root);
1730 template <
typename Key,
typename Value,
typename BytesView>
1731 template <
typename K,
typename>
1738 template <
typename Key,
typename Value,
typename BytesView>
1739 template <
typename K>
1743 auto key = bytes_view(k);
1746 while (n && !n.is_leaf()) {
1747 if (path_length_equal(key.size(), n))
1748 n = n->embedded_entry;
1749 else if (n->byte >= key.size())
1752 n = n->child[slice_index(key[n->byte], n->bit)];
1758 if (!keys_equal(key, bytes_view(n.get_leaf()->key())))
1761 return n.get_leaf();
1771 template <
typename Key,
typename Value,
typename BytesView>
1794 template <
typename Key,
typename Value,
typename BytesView>
1798 auto pop =
pool_base(pmemobj_pool_by_ptr(
this));
1801 auto *
leaf = pos.leaf_;
1802 auto parent =
leaf->parent;
1808 delete_persistent<radix_tree::leaf>(
1815 this->root =
nullptr;
1821 const_cast<tagged_node_ptr &
>(*parent->find_child(
leaf)) =
1827 tagged_node_ptr only_child =
nullptr;
1828 for (
size_t i = 0; i < SLNODES; i++) {
1834 only_child = n->child[i];
1838 if (only_child && n->embedded_entry) {
1842 }
else if (n->embedded_entry) {
1843 only_child = n->embedded_entry;
1847 parent_ref(only_child) = n->parent;
1849 auto *child_slot = parent
1850 ?
const_cast<tagged_node_ptr *
>(&*parent->find_child(n))
1852 *child_slot = only_child;
1854 delete_persistent<radix_tree::node>(n.get_node());
1857 return iterator(
const_cast<typename iterator::leaf_ptr
>(pos.leaf_),
1874 template <
typename Key,
typename Value,
typename BytesView>
1879 auto pop =
pool_base(pmemobj_pool_by_ptr(
this));
1882 while (first != last)
1883 first = erase(first);
1886 return iterator(
const_cast<typename iterator::leaf_ptr
>(first.leaf_),
1902 template <
typename Key,
typename Value,
typename BytesView>
1903 typename radix_tree<Key, Value, BytesView>::size_type
1931 template <
typename Key,
typename Value,
typename BytesView>
1932 template <
typename K,
typename>
1933 typename radix_tree<Key, Value, BytesView>::size_type
1946 template <
typename Key,
typename Value,
typename BytesView>
1947 template <
bool Lower,
typename K>
1951 auto key = bytes_view(k);
1952 auto pop =
pool_base(pmemobj_pool_by_ptr(
this));
1964 auto leaf = common_prefix_leaf(key);
1965 auto leaf_key = bytes_view(leaf->key());
1966 auto diff = prefix_diff(key, leaf_key);
1967 auto sh = bit_diff(leaf_key, key, diff);
1970 if (diff == key.size() && leaf_key.size() == key.size()) {
1972 return const_iterator(leaf, &root);
1974 return ++const_iterator(leaf, &root);
1978 const tagged_node_ptr *slot;
1979 tagged_node_ptr prev;
1980 std::tie(slot, prev) = descend(key, diff, sh);
1983 leaf = next_leaf<node::direction::Forward>(
1984 prev->template make_iterator<node::direction::Forward>(
1988 return const_iterator(leaf, &root);
1996 if (diff == key.size()) {
1997 leaf = find_leaf<node::direction::Forward>(*slot);
1998 return const_iterator(leaf, &root);
2004 if (diff == leaf_key.size())
2005 return ++const_iterator(leaf, &root);
2008 assert(diff < leaf_key.size() && diff < key.size());
2012 if (compare(key, leaf_key, diff) < 0) {
2013 leaf = find_leaf<node::direction::Forward>(*slot);
2014 return const_iterator(leaf, &root);
2017 if (slot == &root) {
2018 return const_iterator(
nullptr, &root);
2023 leaf = next_leaf<node::direction::Forward>(
2024 prev->template make_iterator<node::direction::Forward>(slot),
2027 return const_iterator(leaf, &root);
2040 template <
typename Key,
typename Value,
typename BytesView>
2041 typename radix_tree<Key, Value, BytesView>::const_iterator
2044 return internal_bound<true>(k);
2057 template <
typename Key,
typename Value,
typename BytesView>
2061 auto it =
const_cast<const radix_tree *
>(
this)->lower_bound(k);
2062 return iterator(
const_cast<typename iterator::leaf_ptr
>(it.leaf_),
2079 template <
typename Key,
typename Value,
typename BytesView>
2080 template <
typename K,
typename>
2084 auto it =
const_cast<const radix_tree *
>(
this)->lower_bound(k);
2085 return iterator(
const_cast<typename iterator::leaf_ptr
>(it.leaf_),
2102 template <
typename Key,
typename Value,
typename BytesView>
2103 template <
typename K,
typename>
2107 return internal_bound<true>(k);
2120 template <
typename Key,
typename Value,
typename BytesView>
2124 return internal_bound<false>(k);
2137 template <
typename Key,
typename Value,
typename BytesView>
2141 auto it =
const_cast<const radix_tree *
>(
this)->upper_bound(k);
2142 return iterator(
const_cast<typename iterator::leaf_ptr
>(it.leaf_),
2159 template <
typename Key,
typename Value,
typename BytesView>
2160 template <
typename K,
typename>
2164 auto it =
const_cast<const radix_tree *
>(
this)->upper_bound(k);
2165 return iterator(
const_cast<typename iterator::leaf_ptr
>(it.leaf_),
2182 template <
typename Key,
typename Value,
typename BytesView>
2183 template <
typename K,
typename>
2187 return internal_bound<false>(k);
2196 template <
typename Key,
typename Value,
typename BytesView>
2202 const_cast<typename iterator::leaf_ptr
>(const_begin.leaf_),
2213 template <
typename Key,
typename Value,
typename BytesView>
2217 auto const_end =
const_cast<const radix_tree *
>(
this)->
end();
2219 const_cast<typename iterator::leaf_ptr
>(const_end.leaf_),
2229 template <
typename Key,
typename Value,
typename BytesView>
2237 radix_tree::find_leaf<radix_tree::node::direction::Forward>(
2249 template <
typename Key,
typename Value,
typename BytesView>
2262 template <
typename Key,
typename Value,
typename BytesView>
2276 template <
typename Key,
typename Value,
typename BytesView>
2288 template <
typename Key,
typename Value,
typename BytesView>
2289 typename radix_tree<Key, Value, BytesView>::reverse_iterator
2292 return reverse_iterator(
end());
2301 template <
typename Key,
typename Value,
typename BytesView>
2302 typename radix_tree<Key, Value, BytesView>::reverse_iterator
2305 return reverse_iterator(
begin());
2313 template <
typename Key,
typename Value,
typename BytesView>
2314 typename radix_tree<Key, Value, BytesView>::const_reverse_iterator
2317 return const_reverse_iterator(
cend());
2326 template <
typename Key,
typename Value,
typename BytesView>
2327 typename radix_tree<Key, Value, BytesView>::const_reverse_iterator
2330 return const_reverse_iterator(
cbegin());
2333 template <
typename Key,
typename Value,
typename BytesView>
2334 typename radix_tree<Key, Value, BytesView>::const_reverse_iterator
2337 return const_reverse_iterator(
cend());
2340 template <
typename Key,
typename Value,
typename BytesView>
2341 typename radix_tree<Key, Value, BytesView>::const_reverse_iterator
2344 return const_reverse_iterator(
cbegin());
2347 template <
typename Key,
typename Value,
typename BytesView>
2349 radix_tree<Key, Value, BytesView>::print_rec(std::ostream &os,
2350 radix_tree::tagged_node_ptr n)
2353 os <<
"\"" << n.get_node() <<
"\""
2354 <<
" [style=filled,color=\"blue\"]" << std::endl;
2355 os <<
"\"" << n.get_node() <<
"\" [label=\"byte:" << n->byte
2356 <<
", bit:" << int(n->bit) <<
"\"]" << std::endl;
2358 auto parent = n->parent ? n->parent.get_node() : 0;
2359 os <<
"\"" << n.get_node() <<
"\" -> "
2360 <<
"\"" << parent <<
"\" [label=\"parent\"]" << std::endl;
2362 for (
auto it = n->begin(); it != n->end(); ++it) {
2366 auto ch = it->is_leaf() ? (
void *)it->get_leaf()
2367 : (
void *)it->get_node();
2369 os <<
"\"" << n.get_node() <<
"\" -> \"" << ch <<
"\""
2374 auto bv = bytes_view(n.get_leaf()->key());
2376 os <<
"\"" << n.get_leaf()
2377 <<
"\" [style=filled,color=\"green\"]" << std::endl;
2378 os <<
"\"" << n.get_leaf() <<
"\" [label=\"key:";
2380 for (
size_t i = 0; i < bv.size(); i++)
2383 os <<
"\"]" << std::endl;
2385 auto parent = n.get_leaf()->parent
2386 ? n.get_leaf()->parent.get_node()
2389 os <<
"\"" << n.get_leaf() <<
"\" -> \"" << parent
2390 <<
"\" [label=\"parent\"]" << std::endl;
2392 if (parent && n == parent->embedded_entry) {
2393 os <<
"{rank=same;\"" << parent <<
"\";\""
2394 << n.get_leaf() <<
"\"}" << std::endl;
2402 template <
typename K,
typename V,
typename BV>
2406 os <<
"digraph Radix {" << std::endl;
2411 os <<
"}" << std::endl;
2419 template <
typename Key,
typename Value,
typename BytesView>
2421 radix_tree<Key, Value, BytesView>::slice_index(
char b, uint8_t bit)
2423 return static_cast<unsigned>(b >> bit) & NIB;
2426 template <
typename Key,
typename Value,
typename BytesView>
2427 radix_tree<Key, Value, BytesView>::tagged_node_ptr::tagged_node_ptr(
2431 assert(!(
bool)*
this);
2434 template <
typename Key,
typename Value,
typename BytesView>
2435 radix_tree<Key, Value, BytesView>::tagged_node_ptr::tagged_node_ptr(
2436 const persistent_ptr<leaf> &ptr)
2437 : ptr(add_tag(ptr.
get()))
2439 assert(get_leaf() == ptr.get());
2442 template <
typename Key,
typename Value,
typename BytesView>
2443 radix_tree<Key, Value, BytesView>::tagged_node_ptr::tagged_node_ptr(
2444 const persistent_ptr<node> &ptr)
2447 assert(get_node() == ptr.get());
2450 template <
typename Key,
typename Value,
typename BytesView>
2451 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr &
2452 radix_tree<Key, Value, BytesView>::tagged_node_ptr::operator=(
2456 assert(!(
bool)*
this);
2461 template <
typename Key,
typename Value,
typename BytesView>
2462 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr &
2463 radix_tree<Key, Value, BytesView>::tagged_node_ptr::operator=(
2464 const persistent_ptr<leaf> &rhs)
2466 ptr = add_tag(rhs.get());
2467 assert(get_leaf() == rhs.get());
2472 template <
typename Key,
typename Value,
typename BytesView>
2473 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr &
2474 radix_tree<Key, Value, BytesView>::tagged_node_ptr::operator=(
2475 const persistent_ptr<node> &rhs)
2478 assert(get_node() == rhs.get());
2483 template <
typename Key,
typename Value,
typename BytesView>
2486 const radix_tree::tagged_node_ptr &rhs)
const
2488 return ptr.to_byte_pointer() == rhs.ptr.to_byte_pointer();
2491 template <
typename Key,
typename Value,
typename BytesView>
2494 const radix_tree::tagged_node_ptr &rhs)
const
2496 return !(*
this == rhs);
2499 template <
typename Key,
typename Value,
typename BytesView>
2502 const radix_tree::leaf *rhs)
const
2504 return is_leaf() && get_leaf() == rhs;
2507 template <
typename Key,
typename Value,
typename BytesView>
2510 const radix_tree::leaf *rhs)
const
2512 return !(*
this == rhs);
2515 template <
typename Key,
typename Value,
typename BytesView>
2522 template <
typename Key,
typename Value,
typename BytesView>
2524 radix_tree<Key, Value, BytesView>::tagged_node_ptr::add_tag(
2525 radix_tree::leaf *ptr)
const
2527 auto tagged =
reinterpret_cast<uintptr_t
>(ptr) | uintptr_t(IS_LEAF);
2528 return reinterpret_cast<radix_tree::leaf *
>(tagged);
2531 template <
typename Key,
typename Value,
typename BytesView>
2533 radix_tree<Key, Value, BytesView>::tagged_node_ptr::remove_tag(
void *ptr)
const
2535 auto untagged =
reinterpret_cast<uintptr_t
>(ptr) & ~uintptr_t(IS_LEAF);
2536 return reinterpret_cast<void *
>(untagged);
2539 template <
typename Key,
typename Value,
typename BytesView>
2541 radix_tree<Key, Value, BytesView>::tagged_node_ptr::is_leaf()
const
2543 auto value =
reinterpret_cast<uintptr_t
>(ptr.to_void_pointer());
2544 return value & uintptr_t(IS_LEAF);
2547 template <
typename Key,
typename Value,
typename BytesView>
2548 typename radix_tree<Key, Value, BytesView>::leaf *
2549 radix_tree<Key, Value, BytesView>::tagged_node_ptr::get_leaf()
const
2552 return static_cast<radix_tree::leaf *
>(
2553 remove_tag(ptr.to_void_pointer()));
2556 template <
typename Key,
typename Value,
typename BytesView>
2557 typename radix_tree<Key, Value, BytesView>::node *
2558 radix_tree<Key, Value, BytesView>::tagged_node_ptr::get_node()
const
2561 return static_cast<radix_tree::node *
>(ptr.to_void_pointer());
2564 template <
typename Key,
typename Value,
typename BytesView>
2565 radix_tree<Key, Value, BytesView>::tagged_node_ptr::operator bool() const
2568 return remove_tag(ptr.to_void_pointer()) !=
nullptr;
2571 template <
typename Key,
typename Value,
typename BytesView>
2572 typename radix_tree<Key, Value, BytesView>::node *
2573 radix_tree<Key, Value, BytesView>::tagged_node_ptr::operator->() const
2579 template <
typename Key,
typename Value,
typename BytesView>
2580 radix_tree<Key, Value, BytesView>::node::forward_iterator::forward_iterator(
2581 pointer child,
const node *n)
2582 : child(child), n(n)
2586 template <
typename Key,
typename Value,
typename BytesView>
2587 typename radix_tree<Key, Value, BytesView>::node::forward_iterator
2590 if (child == &n->embedded_entry)
2591 child = &n->child[0];
2598 template <
typename Key,
typename Value,
typename BytesView>
2599 radix_tree<Key, Value, BytesView>::node::node(tagged_node_ptr parent,
2600 byten_t
byte, bitn_t bit)
2601 : parent(parent), byte(byte), bit(bit)
2605 template <
typename Key,
typename Value,
typename BytesView>
2606 typename radix_tree<Key, Value, BytesView>::node::forward_iterator
2609 if (child == &n->child[0])
2610 child = &n->embedded_entry;
2617 template <
typename Key,
typename Value,
typename BytesView>
2618 typename radix_tree<Key, Value, BytesView>::node::forward_iterator
2621 forward_iterator tmp(child, n);
2626 template <
typename Key,
typename Value,
typename BytesView>
2627 typename radix_tree<Key, Value, BytesView>::node::forward_iterator::reference
2628 radix_tree<Key, Value, BytesView>::node::forward_iterator::operator*()
2634 template <
typename Key,
typename Value,
typename BytesView>
2635 typename radix_tree<Key, Value, BytesView>::node::forward_iterator::pointer
2636 radix_tree<Key, Value, BytesView>::node::forward_iterator::operator->()
2642 template <
typename Key,
typename Value,
typename BytesView>
2643 typename radix_tree<Key, Value, BytesView>::node::forward_iterator::pointer
2644 radix_tree<Key, Value, BytesView>::node::forward_iterator::get_node()
const
2649 template <
typename Key,
typename Value,
typename BytesView>
2652 const forward_iterator &rhs)
const
2654 return child == rhs.child && n == rhs.n;
2657 template <
typename Key,
typename Value,
typename BytesView>
2660 const forward_iterator &rhs)
const
2662 return child != rhs.child || n != rhs.n;
2665 template <
typename Key,
typename Value,
typename BytesView>
2666 template <
bool Direction>
2667 typename std::enable_if<
2669 radix_tree<Key, Value, BytesView>::node::direction::Forward,
2670 typename radix_tree<Key, Value,
2671 BytesView>::node::forward_iterator>::type
2674 return forward_iterator(&embedded_entry,
this);
2677 template <
typename Key,
typename Value,
typename BytesView>
2678 template <
bool Direction>
2679 typename std::enable_if<
2681 radix_tree<Key, Value, BytesView>::node::direction::Forward,
2682 typename radix_tree<Key, Value,
2683 BytesView>::node::forward_iterator>::type
2686 return forward_iterator(&child[SLNODES],
this);
2689 template <
typename Key,
typename Value,
typename BytesView>
2690 template <
bool Direction>
2691 typename std::enable_if<
2693 radix_tree<Key, Value, BytesView>::node::direction::Reverse,
2694 typename radix_tree<Key, Value,
2695 BytesView>::node::reverse_iterator>::type
2698 return reverse_iterator(end<direction::Forward>());
2701 template <
typename Key,
typename Value,
typename BytesView>
2702 template <
bool Direction>
2703 typename std::enable_if<
2705 radix_tree<Key, Value, BytesView>::node::direction::Reverse,
2706 typename radix_tree<Key, Value,
2707 BytesView>::node::reverse_iterator>::type
2710 return reverse_iterator(begin<direction::Forward>());
2713 template <
typename Key,
typename Value,
typename BytesView>
2714 template <
bool Direction,
typename Ptr>
2715 typename radix_tree<Key, Value, BytesView>::node::template iterator<Direction>
2716 radix_tree<Key, Value, BytesView>::node::find_child(
const Ptr &n)
const
2718 return std::find(begin<Direction>(), end<Direction>(), n);
2721 template <
typename Key,
typename Value,
typename BytesView>
2722 template <
bool Direction,
typename Enable>
2723 typename radix_tree<Key, Value, BytesView>::node::template iterator<Direction>
2724 radix_tree<Key, Value, BytesView>::node::make_iterator(
2725 const tagged_node_ptr *ptr)
const
2727 return forward_iterator(ptr,
this);
2730 template <
typename Key,
typename Value,
typename BytesView>
2731 template <
bool IsConst>
2732 radix_tree<Key, Value, BytesView>::radix_tree_iterator<
2733 IsConst>::radix_tree_iterator(leaf_ptr leaf_, node_ptr root)
2734 : leaf_(leaf_), root(root)
2738 template <
typename Key,
typename Value,
typename BytesView>
2739 template <
bool IsConst>
2740 template <
bool C,
typename Enable>
2741 radix_tree<Key, Value, BytesView>::radix_tree_iterator<
2742 IsConst>::radix_tree_iterator(
const radix_tree_iterator<false> &rhs)
2747 template <
typename Key,
typename Value,
typename BytesView>
2748 template <
bool IsConst>
2749 typename radix_tree<Key, Value,
2750 BytesView>::template radix_tree_iterator<IsConst>::reference
2751 radix_tree<Key, Value,
2752 BytesView>::radix_tree_iterator<IsConst>::operator*()
const
2758 template <
typename Key,
typename Value,
typename BytesView>
2759 template <
bool IsConst>
2760 typename radix_tree<Key, Value,
2761 BytesView>::template radix_tree_iterator<IsConst>::pointer
2762 radix_tree<Key, Value,
2763 BytesView>::radix_tree_iterator<IsConst>::operator->()
const
2778 template <
typename Key,
typename Value,
typename BytesView>
2779 template <
bool IsConst>
2780 template <
typename V,
typename Enable>
2785 auto pop =
pool_base(pmemobj_pool_by_ptr(leaf_));
2787 if (rhs.
size() <= leaf_->value().capacity()) {
2790 tagged_node_ptr *slot;
2792 if (!leaf_->parent) {
2793 assert(root->get_leaf() == leaf_);
2796 slot =
const_cast<tagged_node_ptr *
>(
2797 &*leaf_->parent->find_child(leaf_));
2800 auto old_leaf = leaf_;
2803 *slot = leaf::make_key_args(old_leaf->parent,
2804 old_leaf->key(), rhs);
2805 delete_persistent<typename radix_tree::leaf>(old_leaf);
2808 leaf_ = slot->get_leaf();
2817 template <
typename Key,
typename Value,
typename BytesView>
2818 template <
bool IsConst>
2819 template <
typename T,
typename V,
typename Enable>
2824 auto pop =
pool_base(pmemobj_pool_by_ptr(leaf_));
2829 template <
typename Key,
typename Value,
typename BytesView>
2830 template <
bool IsConst>
2841 auto it = leaf_->parent->template find_child<
2842 radix_tree::node::direction::Forward>(leaf_);
2844 leaf_ =
const_cast<leaf_ptr
>(
2845 next_leaf<radix_tree::node::direction::Forward>(
2846 it, leaf_->parent));
2852 template <
typename Key,
typename Value,
typename BytesView>
2853 template <
bool IsConst>
2854 typename radix_tree<Key, Value,
2855 BytesView>::template radix_tree_iterator<IsConst> &
2860 leaf_ =
const_cast<leaf_ptr
>(
2861 radix_tree::find_leaf<
2862 radix_tree::node::direction::Reverse>(*root));
2865 assert(leaf_->parent);
2867 auto it = leaf_->parent->template find_child<
2868 radix_tree::node::direction::Reverse>(leaf_);
2870 leaf_ =
const_cast<leaf_ptr
>(
2871 next_leaf<radix_tree::node::direction::Reverse>(
2872 it, leaf_->parent));
2878 template <
typename Key,
typename Value,
typename BytesView>
2879 template <
bool IsConst>
2880 typename radix_tree<Key, Value,
2881 BytesView>::template radix_tree_iterator<IsConst>
2891 template <
typename Key,
typename Value,
typename BytesView>
2892 template <
bool IsConst>
2893 typename radix_tree<Key, Value,
2894 BytesView>::template radix_tree_iterator<IsConst>
2904 template <
typename Key,
typename Value,
typename BytesView>
2905 template <
bool IsConst>
2909 const radix_tree_iterator<C> &rhs)
const
2911 return leaf_ != rhs.leaf_;
2914 template <
typename Key,
typename Value,
typename BytesView>
2915 template <
bool IsConst>
2919 const radix_tree_iterator<C> &rhs)
const
2921 return !(*
this != rhs);
2929 template <
typename Key,
typename Value,
typename BytesView>
2930 template <
bool Direction,
typename Iterator>
2931 typename radix_tree<Key, Value, BytesView>::leaf *
2932 radix_tree<Key, Value, BytesView>::next_leaf(Iterator node,
2933 tagged_node_ptr parent)
2937 }
while (node != parent->template end<Direction>() && !(*node));
2940 if (node == parent->template end<Direction>()) {
2941 auto p = parent->parent;
2945 auto p_it = p->template find_child<Direction>(parent);
2946 return next_leaf<Direction>(p_it, p);
2949 return find_leaf<Direction>(*node);
2956 template <
typename Key,
typename Value,
typename BytesView>
2957 template <
bool Direction>
2958 typename radix_tree<Key, Value, BytesView>::leaf *
2959 radix_tree<Key, Value, BytesView>::find_leaf(
2960 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr n)
2965 return n.get_leaf();
2967 for (
auto it = n->template begin<Direction>();
2968 it != n->template end<Direction>(); ++it) {
2970 return find_leaf<Direction>(*it);
2977 template <
typename Key,
typename Value,
typename BytesView>
2979 radix_tree<Key, Value, BytesView>::leaf::key()
2981 return *
reinterpret_cast<Key *
>(
this + 1);
2984 template <
typename Key,
typename Value,
typename BytesView>
2986 radix_tree<Key, Value, BytesView>::leaf::value()
2988 auto key_dst =
reinterpret_cast<char *
>(
this + 1);
2989 auto val_dst =
reinterpret_cast<Value *
>(
2990 key_dst + total_sizeof<Key>::value(key()));
2992 return *
reinterpret_cast<Value *
>(val_dst);
2995 template <
typename Key,
typename Value,
typename BytesView>
2997 radix_tree<Key, Value, BytesView>::leaf::key()
const
2999 return *
reinterpret_cast<const Key *
>(
this + 1);
3002 template <
typename Key,
typename Value,
typename BytesView>
3004 radix_tree<Key, Value, BytesView>::leaf::value()
const
3006 auto key_dst =
reinterpret_cast<const char *
>(
this + 1);
3007 auto val_dst =
reinterpret_cast<const Value *
>(
3008 key_dst + total_sizeof<Key>::value(key()));
3010 return *
reinterpret_cast<const Value *
>(val_dst);
3013 template <
typename Key,
typename Value,
typename BytesView>
3014 radix_tree<Key, Value, BytesView>::leaf::~leaf()
3016 detail::destroy<Key>(key());
3017 detail::destroy<Value>(value());
3020 template <
typename Key,
typename Value,
typename BytesView>
3021 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3022 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent)
3024 auto t = std::make_tuple();
3025 return make(parent, std::piecewise_construct, t, t,
3026 typename detail::make_index_sequence<>::type{},
3027 typename detail::make_index_sequence<>::type{});
3030 template <
typename Key,
typename Value,
typename BytesView>
3031 template <
typename... Args1,
typename... Args2>
3032 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3033 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3034 std::piecewise_construct_t pc,
3035 std::tuple<Args1...> first_args,
3036 std::tuple<Args2...> second_args)
3038 return make(parent, pc, first_args, second_args,
3039 typename detail::make_index_sequence<Args1...>::type{},
3040 typename detail::make_index_sequence<Args2...>::type{});
3043 template <
typename Key,
typename Value,
typename BytesView>
3044 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3045 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3046 const Key &k,
const Value &v)
3048 return make(parent, std::piecewise_construct, std::forward_as_tuple(k),
3049 std::forward_as_tuple(v));
3052 template <
typename Key,
typename Value,
typename BytesView>
3053 template <
typename K,
typename V>
3054 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3055 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent, K &&k,
3058 return make(parent, std::piecewise_construct,
3059 std::forward_as_tuple(std::forward<K>(k)),
3060 std::forward_as_tuple(std::forward<V>(v)));
3063 template <
typename Key,
typename Value,
typename BytesView>
3064 template <
typename K,
typename... Args>
3065 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3066 radix_tree<Key, Value, BytesView>::leaf::make_key_args(tagged_node_ptr parent,
3067 K &&k, Args &&... args)
3069 return make(parent, std::piecewise_construct,
3070 std::forward_as_tuple(std::forward<K>(k)),
3071 std::forward_as_tuple(std::forward<Args>(args)...));
3074 template <
typename Key,
typename Value,
typename BytesView>
3075 template <
typename K,
typename V>
3076 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3077 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3078 detail::pair<K, V> &&p)
3080 return make(parent, std::piecewise_construct,
3081 std::forward_as_tuple(std::forward<K>(p.first)),
3082 std::forward_as_tuple(std::forward<V>(p.second)));
3085 template <
typename Key,
typename Value,
typename BytesView>
3086 template <
typename K,
typename V>
3087 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3088 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3089 const detail::pair<K, V> &p)
3091 return make(parent, std::piecewise_construct,
3092 std::forward_as_tuple(p.first),
3093 std::forward_as_tuple(p.second));
3096 template <
typename Key,
typename Value,
typename BytesView>
3097 template <
typename K,
typename V>
3098 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3099 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3100 std::pair<K, V> &&p)
3102 return make(parent, std::piecewise_construct,
3103 std::forward_as_tuple(std::forward<K>(p.first)),
3104 std::forward_as_tuple(std::forward<V>(p.second)));
3107 template <
typename Key,
typename Value,
typename BytesView>
3108 template <
typename K,
typename V>
3109 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3110 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3111 const std::pair<K, V> &p)
3113 return make(parent, std::piecewise_construct,
3114 std::forward_as_tuple(p.first),
3115 std::forward_as_tuple(p.second));
3118 template <
typename Key,
typename Value,
typename BytesView>
3119 template <
typename... Args1,
typename... Args2,
size_t... I1,
size_t... I2>
3120 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3121 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3122 std::piecewise_construct_t,
3123 std::tuple<Args1...> &first_args,
3124 std::tuple<Args2...> &second_args,
3125 detail::index_sequence<I1...>,
3126 detail::index_sequence<I2...>)
3128 standard_alloc_policy<void> a;
3129 auto key_size = total_sizeof<Key>::value(std::get<I1>(first_args)...);
3131 total_sizeof<Value>::value(std::get<I2>(second_args)...);
3132 auto ptr =
static_cast<persistent_ptr<leaf>
>(
3133 a.allocate(
sizeof(leaf) + key_size + val_size));
3135 auto key_dst =
reinterpret_cast<Key *
>(ptr.get() + 1);
3136 auto val_dst =
reinterpret_cast<Value *
>(
3137 reinterpret_cast<char *
>(key_dst) + key_size);
3139 new (ptr.get()) leaf();
3140 new (key_dst) Key(std::forward<Args1>(std::get<I1>(first_args))...);
3141 new (val_dst) Value(std::forward<Args2>(std::get<I2>(second_args))...);
3143 ptr->parent = parent;
3148 template <
typename Key,
typename Value,
typename BytesView>
3149 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3150 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3153 return make(parent, other.key(), other.value());
3162 template <
typename Key,
typename Value,
typename BytesView>
3166 if (
nullptr == pmemobj_pool_by_ptr(
this))
3177 template <
typename Key,
typename Value,
typename BytesView>
3181 if (pmemobj_tx_stage() != TX_STAGE_WORK)
3183 "Function called out of transaction scope.");
3189 template <
typename Key,
typename Value,
typename BytesView>
3205 struct is_string : std::false_type {
3208 template <
typename CharT,
typename Traits>
3209 struct is_string<obj::basic_string<CharT, Traits>> : std::true_type {
3212 template <
typename CharT,
typename Traits>
3213 struct is_string<obj::experimental::basic_inline_string<CharT, Traits>>
3217 template <
typename T>
3218 struct bytes_view<T, typename std::enable_if<is_string<T>::value>::type> {
3219 using CharT =
typename T::value_type;
3220 using Traits =
typename T::traits_type;
3224 typename Enable =
typename std::enable_if<std::is_constructible<
3225 obj::basic_string_view<CharT, Traits>, C>::value>::type>
3226 bytes_view(
const C *s) : s(*s)
3230 char operator[](std::size_t p)
const
3232 return static_cast<char>(s[p]);
3241 obj::basic_string_view<CharT, Traits> s;
3243 using is_transparent = void;
3246 template <
typename T>
3247 struct bytes_view<T,
3248 typename std::enable_if<std::is_integral<T>::value &&
3249 !std::is_signed<T>::value>::type> {
3250 bytes_view(
const T *k) : k(k)
3252 #if __cpp_lib_endian
3254 std::endian::native == std::endian::little,
3255 "Scalar type are not little endian on this platform!");
3256 #elif !defined(NDEBUG)
3258 uint16_t word = (2 << 8) + 1;
3259 assert(((
char *)&word)[0] == 1);
3263 char operator[](std::size_t p)
const
3265 return reinterpret_cast<const char *
>(k)[size() - p - 1];