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
103 template <
typename Key,
typename Value,
104 typename BytesView = detail::bytes_view<Key>>
106 template <
bool IsConst>
110 using key_type = Key;
111 using mapped_type = Value;
112 using value_type = detail::pair<const key_type, mapped_type>;
113 using size_type = std::size_t;
114 using reference = value_type &;
115 using const_reference =
const value_type &;
118 using reverse_iterator = std::reverse_iterator<iterator>;
119 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
120 using difference_type = std::ptrdiff_t;
124 template <
class InputIt>
128 radix_tree(std::initializer_list<value_type> il);
136 template <
class... Args>
137 std::pair<iterator, bool> emplace(Args &&... args);
139 std::pair<iterator, bool>
insert(
const value_type &
v);
140 std::pair<iterator, bool>
insert(value_type &&
v);
141 template <
typename P,
142 typename =
typename std::enable_if<
143 std::is_constructible<value_type, P &&>::value,
145 std::pair<iterator, bool>
insert(P &&
p);
153 template <
class InputIterator>
154 void insert(InputIterator first, InputIterator last);
155 void insert(std::initializer_list<value_type> il);
159 template <
class... Args>
160 std::pair<iterator, bool> try_emplace(
const key_type &k,
162 template <
class... Args>
163 std::pair<iterator, bool> try_emplace(key_type &&k, Args &&... args);
171 template <
typename K,
typename BV = BytesView,
class... Args>
172 auto try_emplace(K &&k, Args &&... args) ->
typename std::enable_if<
173 detail::has_is_transparent<BV>::value &&
174 !std::is_same<
typename std::remove_const<
175 typename std::remove_reference<
178 std::pair<iterator, bool>>::type;
180 template <
typename M>
181 std::pair<iterator, bool> insert_or_assign(
const key_type &k, M &&obj);
182 template <
typename M>
183 std::pair<iterator, bool> insert_or_assign(key_type &&k, M &&obj);
190 typename M,
typename K,
191 typename =
typename std::enable_if<
192 detail::has_is_transparent<BytesView>::value, K>::type>
193 std::pair<iterator, bool> insert_or_assign(K &&k, M &&obj);
197 size_type
erase(
const key_type &k);
198 template <
typename K,
199 typename =
typename std::enable_if<
200 detail::has_is_transparent<BytesView>::value &&
201 !std::is_same<K, iterator>::value &&
202 !std::is_same<K, const_iterator>::value,
204 size_type
erase(
const K &k);
208 size_type
count(
const key_type &k)
const;
211 typename =
typename std::enable_if<
212 detail::has_is_transparent<BytesView>::value, K>::type>
213 size_type
count(
const K &k)
const;
219 typename =
typename std::enable_if<
220 detail::has_is_transparent<BytesView>::value, K>::type>
224 typename =
typename std::enable_if<
225 detail::has_is_transparent<BytesView>::value, K>::type>
232 typename =
typename std::enable_if<
233 detail::has_is_transparent<BytesView>::value, K>::type>
237 typename =
typename std::enable_if<
238 detail::has_is_transparent<BytesView>::value, K>::type>
245 typename =
typename std::enable_if<
246 detail::has_is_transparent<BytesView>::value, K>::type>
250 typename =
typename std::enable_if<
251 detail::has_is_transparent<BytesView>::value, K>::type>
261 reverse_iterator
rbegin();
262 reverse_iterator
rend();
263 const_reverse_iterator
crbegin()
const;
264 const_reverse_iterator
crend()
const;
265 const_reverse_iterator
rbegin()
const;
266 const_reverse_iterator
rend()
const;
269 bool empty()
const noexcept;
270 size_type
max_size()
const noexcept;
271 uint64_t
size()
const noexcept;
275 template <
typename K,
typename V,
typename BV>
276 friend std::ostream &
operator<<(std::ostream &os,
280 using byten_t = uint64_t;
281 using bitn_t = uint8_t;
284 static constexpr std::size_t SLICE = 4;
286 static constexpr std::size_t NIB = ((1ULL << SLICE) - 1);
288 static constexpr std::size_t SLNODES = (1 << SLICE);
290 static constexpr bitn_t SLICE_MASK = (bitn_t) ~(SLICE - 1);
292 static constexpr bitn_t FIRST_NIB = 8 - SLICE;
294 struct tagged_node_ptr;
299 tagged_node_ptr root;
303 template <
typename K,
typename F,
class... Args>
304 std::pair<iterator, bool> internal_emplace(
const K &, F &&);
305 template <
typename K>
306 leaf *internal_find(
const K &k)
const;
308 static tagged_node_ptr &parent_ref(tagged_node_ptr n);
309 template <
typename K1,
typename K2>
310 static bool keys_equal(
const K1 &k1,
const K2 &k2);
311 template <
typename K1,
typename K2>
312 static int compare(
const K1 &k1,
const K2 &k2, byten_t offset = 0);
313 template <
bool Direction,
typename Iterator>
314 static leaf *next_leaf(Iterator child, tagged_node_ptr parent);
315 template <
bool Direction>
316 static leaf *find_leaf(tagged_node_ptr n);
317 static unsigned slice_index(
char k, uint8_t shift);
318 template <
typename K1,
typename K2>
319 static byten_t prefix_diff(
const K1 &lhs,
const K2 &rhs,
321 leaf *any_leftmost_leaf(tagged_node_ptr n, size_type min_depth)
const;
322 template <
typename K1,
typename K2>
323 static bitn_t bit_diff(
const K1 &leaf_key,
const K2 &key, byten_t diff);
324 template <
typename K>
325 leaf *common_prefix_leaf(
const K &key)
const;
326 static void print_rec(std::ostream &os, radix_tree::tagged_node_ptr n);
327 template <
typename K>
328 static BytesView bytes_view(
const K &k);
330 static bool path_length_equal(
size_t key_size, tagged_node_ptr n);
331 template <
typename K>
332 std::tuple<const tagged_node_ptr *, tagged_node_ptr>
333 descend(
const K &k, byten_t diff, bitn_t sh)
const;
334 template <
typename K>
335 std::tuple<tagged_node_ptr *, tagged_node_ptr>
336 descend(
const K &k, byten_t diff, bitn_t sh);
337 template <
bool Lower,
typename K>
343 static_assert(
sizeof(
node) == 256,
344 "Internal node should have size equal to 256 bytes.");
347 template <
typename Key,
typename Value,
typename BytesView>
351 template <
typename Key,
typename Value,
typename BytesView>
352 struct radix_tree<Key, Value, BytesView>::tagged_node_ptr {
353 tagged_node_ptr() =
default;
354 tagged_node_ptr(
const tagged_node_ptr &rhs) =
default;
356 tagged_node_ptr(std::nullptr_t);
360 tagged_node_ptr &
operator=(
const tagged_node_ptr &rhs) =
default;
362 tagged_node_ptr &
operator=(std::nullptr_t);
366 bool operator==(
const tagged_node_ptr &rhs)
const;
367 bool operator!=(
const tagged_node_ptr &rhs)
const;
372 void swap(tagged_node_ptr &rhs);
374 bool is_leaf()
const;
381 explicit operator
bool() const noexcept;
384 static constexpr uintptr_t IS_LEAF = 1;
386 void *remove_tag(
void *ptr) const;
400 template <typename Key, typename Value, typename BytesView>
415 const Key &key()
const;
416 const Value &value()
const;
420 template <
typename... Args1,
typename... Args2>
422 make(tagged_node_ptr parent, std::piecewise_construct_t pc,
423 std::tuple<Args1...> first_args, std::tuple<Args2...> second_args);
424 template <
typename K,
typename V>
428 template <
typename K,
typename... Args>
431 template <
typename K,
typename V>
433 detail::pair<K, V> &&
p);
434 template <
typename K,
typename V>
436 const detail::pair<K, V> &
p);
437 template <
typename K,
typename V>
439 std::pair<K, V> &&
p);
440 template <
typename K,
typename V>
442 const std::pair<K, V> &
p);
447 friend class radix_tree<Key, Value, BytesView>;
451 template <
typename... Args1,
typename... Args2,
size_t... I1,
454 make(tagged_node_ptr parent, std::piecewise_construct_t,
455 std::tuple<Args1...> &first_args,
456 std::tuple<Args2...> &second_args, detail::index_sequence<I1...>,
457 detail::index_sequence<I2...>);
459 tagged_node_ptr parent =
nullptr;
466 template <
typename Key,
typename Value,
typename BytesView>
468 node(tagged_node_ptr parent, byten_t
byte, bitn_t bit);
484 tagged_node_ptr child[SLNODES];
500 static constexpr
bool Forward = 0;
501 static constexpr
bool Reverse = 1;
504 struct forward_iterator;
505 using reverse_iterator = std::reverse_iterator<forward_iterator>;
507 template <
bool Direction>
509 typename std::conditional<Direction == direction::Forward,
511 reverse_iterator>::type;
513 template <
bool Direction = direction::Forward>
514 typename std::enable_if<
517 BytesView>::node::direction::Forward,
519 BytesView>::node::forward_iterator>::type
522 template <
bool Direction = direction::Forward>
523 typename std::enable_if<
526 BytesView>::node::direction::Forward,
528 BytesView>::node::forward_iterator>::type
532 template <
bool Direction = direction::Forward>
533 typename std::enable_if<
536 BytesView>::node::direction::Reverse,
538 BytesView>::node::reverse_iterator>::type
542 template <
bool Direction = direction::Forward>
543 typename std::enable_if<
546 BytesView>::node::direction::Reverse,
548 BytesView>::node::reverse_iterator>::type
551 template <
bool Direction = direction::Forward,
typename Ptr>
554 template <
bool Direction = direction::Forward,
555 typename Enable =
typename std::enable_if<
556 Direction == direction::Forward>::type>
559 uint8_t padding[256 -
sizeof(parent) -
sizeof(
leaf) -
sizeof(child) -
560 sizeof(
byte) -
sizeof(bit)];
568 template <
typename Key,
typename Value,
typename BytesView>
569 template <
bool IsConst>
573 typename std::conditional<IsConst, const leaf *, leaf *>::type;
575 typename std::conditional<IsConst,
const tagged_node_ptr *,
576 tagged_node_ptr *>::type;
580 using difference_type = std::ptrdiff_t;
582 using reference =
typename std::conditional<IsConst,
const value_type &,
584 using pointer =
typename std::conditional<IsConst,
value_type const *,
586 using iterator_category = std::bidirectional_iterator_tag;
592 template <
bool C = IsConst,
593 typename Enable =
typename std::enable_if<C>::type>
599 reference operator*()
const;
600 pointer operator->()
const;
602 template <
typename V = Value,
603 typename Enable =
typename std::enable_if<
604 detail::is_inline_string<V>::value>::type>
606 typename V::traits_type>
609 template <
typename T,
typename V = Value,
610 typename Enable =
typename std::enable_if<
611 !detail::is_inline_string<V>::value>::type>
612 void assign_val(T &&rhs);
629 leaf_ptr leaf_ =
nullptr;
630 node_ptr root =
nullptr;
633 template <
typename Key,
typename Value,
typename BytesView>
634 struct radix_tree<Key, Value, BytesView>::node::forward_iterator {
635 using difference_type = std::ptrdiff_t;
636 using value_type = tagged_node_ptr;
637 using pointer =
const value_type *;
638 using reference =
const value_type &;
639 using iterator_category = std::forward_iterator_tag;
641 forward_iterator(pointer child,
const node *
node);
648 reference operator*()
const;
649 pointer operator->()
const;
651 pointer get_node()
const;
653 bool operator!=(
const forward_iterator &rhs)
const;
654 bool operator==(
const forward_iterator &rhs)
const;
669 template <
typename Key,
typename Value,
typename BytesView>
695 template <
typename Key,
typename Value,
typename BytesView>
696 template <
class InputIt>
698 : root(nullptr), size_(0)
703 for (
auto it = first; it != last; it++)
722 template <
typename Key,
typename Value,
typename BytesView>
726 check_tx_stage_work();
731 for (
auto it = m.
cbegin(); it != m.
cend(); it++)
747 template <
typename Key,
typename Value,
typename BytesView>
751 check_tx_stage_work();
773 template <
typename Key,
typename Value,
typename BytesView>
775 std::initializer_list<value_type> il)
789 template <
typename Key,
typename Value,
typename BytesView>
797 if (
this != &other) {
801 this->root =
nullptr;
804 for (
auto it = other.
cbegin(); it != other.
cend(); it++)
820 template <
typename Key,
typename Value,
typename BytesView>
828 if (
this != &other) {
832 this->root = other.root;
833 this->size_ = other.size_;
834 other.root =
nullptr;
852 template <
typename Key,
typename Value,
typename BytesView>
855 std::initializer_list<value_type> ilist)
864 this->root =
nullptr;
867 for (
auto it = ilist.begin(); it != ilist.end(); it++)
877 template <
typename Key,
typename Value,
typename BytesView>
892 template <
typename Key,
typename Value,
typename BytesView>
902 template <
typename Key,
typename Value,
typename BytesView>
903 typename radix_tree<Key, Value, BytesView>::size_type
906 return std::numeric_limits<difference_type>::max();
912 template <
typename Key,
typename Value,
typename BytesView>
924 template <
typename Key,
typename Value,
typename BytesView>
931 this->size_.swap(rhs.size_);
932 this->root.swap(rhs.root);
939 template <
typename Key,
typename Value,
typename BytesView>
944 return n.get_leaf()->parent;
955 template <
typename Key,
typename Value,
typename BytesView>
956 typename radix_tree<Key, Value, BytesView>::leaf *
957 radix_tree<Key, Value, BytesView>::any_leftmost_leaf(
958 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr n,
959 size_type min_depth)
const
963 while (!n.is_leaf()) {
964 if (n->embedded_entry && n->byte >= min_depth)
965 return n->embedded_entry.get_leaf();
967 for (
size_t i = 0; i < SLNODES; i++) {
969 if ((m = n->child[i])) {
982 template <
typename Key,
typename Value,
typename BytesView>
983 template <
typename K>
984 typename radix_tree<Key, Value, BytesView>::leaf *
985 radix_tree<Key, Value, BytesView>::common_prefix_leaf(
const K &key)
const
989 while (n && !n.is_leaf() && n->byte < key.size()) {
990 auto nn = n->child[slice_index(key[n->byte], n->bit)];
995 n = any_leftmost_leaf(n, key.size());
1003 n = any_leftmost_leaf(n, key.size());
1005 return n.get_leaf();
1008 template <
typename Key,
typename Value,
typename BytesView>
1009 template <
typename K>
1011 radix_tree<Key, Value, BytesView>::bytes_view(
const K &key)
1016 return BytesView(&key);
1019 template <
typename Key,
typename Value,
typename BytesView>
1021 radix_tree<Key, Value, BytesView>::bytes_view(string_view key)
1029 template <
typename Key,
typename Value,
typename BytesView>
1030 template <
typename K1,
typename K2>
1032 radix_tree<Key, Value, BytesView>::keys_equal(
const K1 &k1,
const K2 &k2)
1034 return k1.size() == k2.size() && compare(k1, k2) == 0;
1040 template <
typename Key,
typename Value,
typename BytesView>
1041 template <
typename K1,
typename K2>
1043 radix_tree<Key, Value, BytesView>::compare(
const K1 &k1,
const K2 &k2,
1046 auto ret = prefix_diff(k1, k2, offset);
1048 if (ret != (std::min)(k1.size(), k2.size()))
1049 return (
unsigned char)(k1[ret]) - (
unsigned char)(k2[ret]);
1051 return k1.size() - k2.size();
1057 template <
typename Key,
typename Value,
typename BytesView>
1058 template <
typename K1,
typename K2>
1059 typename radix_tree<Key, Value, BytesView>::byten_t
1060 radix_tree<Key, Value, BytesView>::prefix_diff(
const K1 &lhs,
const K2 &rhs,
1064 for (diff = offset; diff < (std::min)(lhs.size(), rhs.size()); diff++) {
1065 if (lhs[diff] != rhs[diff])
1076 template <
typename Key,
typename Value,
typename BytesView>
1078 radix_tree<Key, Value, BytesView>::path_length_equal(
size_t key_size,
1081 return n->byte == key_size && n->bit == bitn_t(FIRST_NIB);
1084 template <
typename Key,
typename Value,
typename BytesView>
1085 template <
typename K1,
typename K2>
1086 typename radix_tree<Key, Value, BytesView>::bitn_t
1087 radix_tree<Key, Value, BytesView>::bit_diff(
const K1 &leaf_key,
const K2 &key,
1090 auto min_key_len = (std::min)(leaf_key.size(), key.size());
1096 if (diff < min_key_len) {
1098 static_cast<unsigned char>(leaf_key[diff] ^ key[diff]);
1099 sh = pmem::detail::mssb_index((uint32_t)at) & SLICE_MASK;
1105 template <
typename Key,
typename Value,
typename BytesView>
1106 template <
typename K>
1107 std::tuple<const typename radix_tree<Key, Value, BytesView>::tagged_node_ptr *,
1108 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr>
1109 radix_tree<Key, Value, BytesView>::descend(
const K &key, byten_t diff,
1116 while (n && !n.is_leaf() &&
1117 (n->byte < diff || (n->byte == diff && n->bit >= sh))) {
1119 slot = &n->child[slice_index(key[n->byte], n->bit)];
1123 return {slot, prev};
1126 template <
typename Key,
typename Value,
typename BytesView>
1127 template <
typename K>
1128 std::tuple<typename radix_tree<Key, Value, BytesView>::tagged_node_ptr *,
1129 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr>
1130 radix_tree<Key, Value, BytesView>::descend(
const K &key, byten_t diff,
1133 const tagged_node_ptr *slot;
1134 tagged_node_ptr prev;
1136 std::tie(slot, prev) =
1137 const_cast<const radix_tree *
>(
this)->descend(key, diff, sh);
1139 return {
const_cast<tagged_node_ptr *
>(slot), prev};
1142 template <
typename Key,
typename Value,
typename BytesView>
1143 template <
typename K,
typename F,
class... Args>
1144 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1145 radix_tree<Key, Value, BytesView>::internal_emplace(
const K &k, F &&make_leaf)
1147 auto key = bytes_view(k);
1148 auto pop = pool_base(pmemobj_pool_by_ptr(
this));
1152 [&] { this->root = make_leaf(
nullptr); });
1153 return {iterator(root.get_leaf(), &root),
true};
1163 auto leaf = common_prefix_leaf(key);
1164 auto leaf_key = bytes_view(leaf->key());
1165 auto diff = prefix_diff(key, leaf_key);
1166 auto sh = bit_diff(leaf_key, key, diff);
1169 if (diff == key.size() && leaf_key.size() == key.size())
1170 return {iterator(leaf, &root),
false};
1173 tagged_node_ptr *slot;
1174 tagged_node_ptr prev;
1175 std::tie(slot, prev) = descend(key, diff, sh);
1185 assert(diff < (std::min)(leaf_key.size(), key.size()));
1188 return {iterator(slot->get_leaf(), &root),
true};
1193 if (diff == key.size()) {
1194 if (!n.is_leaf() && path_length_equal(key.size(), n)) {
1195 assert(!n->embedded_entry);
1198 pop, [&] { n->embedded_entry = make_leaf(n); });
1200 return {iterator(n->embedded_entry.get_leaf(), &root),
1206 tagged_node_ptr node;
1208 node = make_persistent<radix_tree::node>(
1209 parent_ref(n), diff, bitn_t(FIRST_NIB));
1210 node->embedded_entry = make_leaf(node);
1211 node->child[slice_index(leaf_key[diff],
1212 bitn_t(FIRST_NIB))] = n;
1214 parent_ref(n) = node;
1218 return {iterator(node->embedded_entry.get_leaf(), &root),
true};
1221 if (diff == leaf_key.size()) {
1224 tagged_node_ptr node;
1228 node = make_persistent<radix_tree::node>(
1229 parent_ref(n), diff, bitn_t(FIRST_NIB));
1230 node->embedded_entry = n;
1231 node->child[slice_index(key[diff], bitn_t(FIRST_NIB))] =
1234 parent_ref(n) = node;
1238 return {iterator(node->child[slice_index(key[diff],
1249 tagged_node_ptr node;
1251 node = make_persistent<radix_tree::node>(parent_ref(n), diff,
1253 node->child[slice_index(leaf_key[diff], sh)] = n;
1254 node->child[slice_index(key[diff], sh)] = make_leaf(node);
1256 parent_ref(n) = node;
1260 return {iterator(node->child[slice_index(key[diff], sh)].get_leaf(),
1293 template <
typename Key,
typename Value,
typename BytesView>
1294 template <
class... Args>
1295 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1299 return internal_emplace(k, [&](tagged_node_ptr parent) {
1301 return leaf::make_key_args(parent, k,
1302 std::forward<Args>(args)...);
1332 template <
typename Key,
typename Value,
typename BytesView>
1333 template <
class... Args>
1334 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1337 auto pop =
pool_base(pmemobj_pool_by_ptr(
this));
1338 std::pair<iterator, bool> ret;
1341 auto leaf_ = leaf::make(
nullptr, std::forward<Args>(args)...);
1342 auto make_leaf = [&](tagged_node_ptr parent) {
1343 leaf_->parent = parent;
1348 ret = internal_emplace(leaf_->key(), make_leaf);
1351 delete_persistent<leaf>(leaf_);
1372 template <
typename Key,
typename Value,
typename BytesView>
1373 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1376 return try_emplace(
v.first,
v.second);
1394 template <
typename Key,
typename Value,
typename BytesView>
1395 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1398 return try_emplace(std::move(
v.first), std::move(
v.second));
1420 template <
typename Key,
typename Value,
typename BytesView>
1421 template <
typename P,
typename>
1422 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1425 return emplace(std::forward<P>(
p));
1439 template <
typename Key,
typename Value,
typename BytesView>
1440 template <
typename InputIterator>
1445 for (
auto it = first; it != last; it++)
1446 try_emplace((*it).first, (*it).second);
1459 template <
typename Key,
typename Value,
typename BytesView>
1463 insert(il.begin(), il.end());
1490 template <
typename Key,
typename Value,
typename BytesView>
1491 template <
class... Args>
1492 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1495 return internal_emplace(k, [&](tagged_node_ptr parent) {
1497 return leaf::make_key_args(parent, std::move(k),
1498 std::forward<Args>(args)...);
1530 template <
typename Key,
typename Value,
typename BytesView>
1531 template <
typename K,
typename BV,
class... Args>
1534 typename std::enable_if<
1535 detail::has_is_transparent<BV>::value &&
1536 !std::is_same<
typename std::remove_const<
1537 typename std::remove_reference<
1540 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
1544 return internal_emplace(k, [&](tagged_node_ptr parent) {
1546 return leaf::make_key_args(parent, std::forward<K>(k),
1547 std::forward<Args>(args)...);
1569 template <
typename Key,
typename Value,
typename BytesView>
1570 template <
typename M>
1571 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1574 auto ret = try_emplace(k, std::forward<M>(obj));
1576 ret.first.assign_val(std::forward<M>(obj));
1598 template <
typename Key,
typename Value,
typename BytesView>
1599 template <
typename M>
1600 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1603 auto ret = try_emplace(std::move(k), std::forward<M>(obj));
1605 ret.first.assign_val(std::forward<M>(obj));
1630 template <
typename Key,
typename Value,
typename BytesView>
1631 template <
typename M,
typename K,
typename>
1632 std::pair<typename radix_tree<Key, Value, BytesView>::iterator,
bool>
1635 auto ret = try_emplace(std::forward<K>(k), std::forward<M>(obj));
1637 ret.first.assign_val(std::forward<M>(obj));
1650 template <
typename Key,
typename Value,
typename BytesView>
1651 typename radix_tree<Key, Value, BytesView>::size_type
1654 return internal_find(k) !=
nullptr ? 1 : 0;
1669 template <
typename Key,
typename Value,
typename BytesView>
1670 template <
typename K,
typename>
1671 typename radix_tree<Key, Value, BytesView>::size_type
1674 return internal_find(k) !=
nullptr ? 1 : 0;
1685 template <
typename Key,
typename Value,
typename BytesView>
1689 return iterator(internal_find(k), &root);
1700 template <
typename Key,
typename Value,
typename BytesView>
1718 template <
typename Key,
typename Value,
typename BytesView>
1719 template <
typename K,
typename>
1723 return iterator(internal_find(k), &root);
1737 template <
typename Key,
typename Value,
typename BytesView>
1738 template <
typename K,
typename>
1745 template <
typename Key,
typename Value,
typename BytesView>
1746 template <
typename K>
1750 auto key = bytes_view(k);
1753 while (n && !n.is_leaf()) {
1754 if (path_length_equal(key.size(), n))
1755 n = n->embedded_entry;
1756 else if (n->byte >= key.size())
1759 n = n->child[slice_index(key[n->byte], n->bit)];
1765 if (!keys_equal(key, bytes_view(n.get_leaf()->key())))
1768 return n.get_leaf();
1778 template <
typename Key,
typename Value,
typename BytesView>
1801 template <
typename Key,
typename Value,
typename BytesView>
1805 auto pop =
pool_base(pmemobj_pool_by_ptr(
this));
1808 auto *
leaf = pos.leaf_;
1809 auto parent =
leaf->parent;
1815 delete_persistent<radix_tree::leaf>(
1822 this->root =
nullptr;
1828 const_cast<tagged_node_ptr &
>(*parent->find_child(
leaf)) =
1834 tagged_node_ptr only_child =
nullptr;
1835 for (
size_t i = 0; i < SLNODES; i++) {
1841 only_child = n->child[i];
1845 if (only_child && n->embedded_entry) {
1849 }
else if (n->embedded_entry) {
1850 only_child = n->embedded_entry;
1854 parent_ref(only_child) = n->parent;
1856 auto *child_slot = parent
1857 ?
const_cast<tagged_node_ptr *
>(&*parent->find_child(n))
1859 *child_slot = only_child;
1861 delete_persistent<radix_tree::node>(n.get_node());
1864 return iterator(
const_cast<typename iterator::leaf_ptr
>(pos.leaf_),
1881 template <
typename Key,
typename Value,
typename BytesView>
1886 auto pop =
pool_base(pmemobj_pool_by_ptr(
this));
1889 while (first != last)
1890 first = erase(first);
1893 return iterator(
const_cast<typename iterator::leaf_ptr
>(first.leaf_),
1909 template <
typename Key,
typename Value,
typename BytesView>
1910 typename radix_tree<Key, Value, BytesView>::size_type
1938 template <
typename Key,
typename Value,
typename BytesView>
1939 template <
typename K,
typename>
1940 typename radix_tree<Key, Value, BytesView>::size_type
1953 template <
typename Key,
typename Value,
typename BytesView>
1954 template <
bool Lower,
typename K>
1958 auto key = bytes_view(k);
1959 auto pop =
pool_base(pmemobj_pool_by_ptr(
this));
1971 auto leaf = common_prefix_leaf(key);
1972 auto leaf_key = bytes_view(leaf->key());
1973 auto diff = prefix_diff(key, leaf_key);
1974 auto sh = bit_diff(leaf_key, key, diff);
1977 if (diff == key.size() && leaf_key.size() == key.size()) {
1979 return const_iterator(leaf, &root);
1981 return ++const_iterator(leaf, &root);
1985 const tagged_node_ptr *slot;
1986 tagged_node_ptr prev;
1987 std::tie(slot, prev) = descend(key, diff, sh);
1990 leaf = next_leaf<node::direction::Forward>(
1991 prev->template make_iterator<node::direction::Forward>(
1995 return const_iterator(leaf, &root);
2003 if (diff == key.size()) {
2004 leaf = find_leaf<node::direction::Forward>(*slot);
2005 return const_iterator(leaf, &root);
2011 if (diff == leaf_key.size())
2012 return ++const_iterator(leaf, &root);
2015 assert(diff < leaf_key.size() && diff < key.size());
2019 if (compare(key, leaf_key, diff) < 0) {
2020 leaf = find_leaf<node::direction::Forward>(*slot);
2021 return const_iterator(leaf, &root);
2024 if (slot == &root) {
2025 return const_iterator(
nullptr, &root);
2030 leaf = next_leaf<node::direction::Forward>(
2031 prev->template make_iterator<node::direction::Forward>(slot),
2034 return const_iterator(leaf, &root);
2047 template <
typename Key,
typename Value,
typename BytesView>
2048 typename radix_tree<Key, Value, BytesView>::const_iterator
2051 return internal_bound<true>(k);
2064 template <
typename Key,
typename Value,
typename BytesView>
2068 auto it =
const_cast<const radix_tree *
>(
this)->lower_bound(k);
2069 return iterator(
const_cast<typename iterator::leaf_ptr
>(it.leaf_),
2086 template <
typename Key,
typename Value,
typename BytesView>
2087 template <
typename K,
typename>
2091 auto it =
const_cast<const radix_tree *
>(
this)->lower_bound(k);
2092 return iterator(
const_cast<typename iterator::leaf_ptr
>(it.leaf_),
2109 template <
typename Key,
typename Value,
typename BytesView>
2110 template <
typename K,
typename>
2114 return internal_bound<true>(k);
2127 template <
typename Key,
typename Value,
typename BytesView>
2131 return internal_bound<false>(k);
2144 template <
typename Key,
typename Value,
typename BytesView>
2148 auto it =
const_cast<const radix_tree *
>(
this)->upper_bound(k);
2149 return iterator(
const_cast<typename iterator::leaf_ptr
>(it.leaf_),
2166 template <
typename Key,
typename Value,
typename BytesView>
2167 template <
typename K,
typename>
2171 auto it =
const_cast<const radix_tree *
>(
this)->upper_bound(k);
2172 return iterator(
const_cast<typename iterator::leaf_ptr
>(it.leaf_),
2189 template <
typename Key,
typename Value,
typename BytesView>
2190 template <
typename K,
typename>
2194 return internal_bound<false>(k);
2203 template <
typename Key,
typename Value,
typename BytesView>
2209 const_cast<typename iterator::leaf_ptr
>(const_begin.leaf_),
2220 template <
typename Key,
typename Value,
typename BytesView>
2224 auto const_end =
const_cast<const radix_tree *
>(
this)->
end();
2226 const_cast<typename iterator::leaf_ptr
>(const_end.leaf_),
2236 template <
typename Key,
typename Value,
typename BytesView>
2244 radix_tree::find_leaf<radix_tree::node::direction::Forward>(
2256 template <
typename Key,
typename Value,
typename BytesView>
2269 template <
typename Key,
typename Value,
typename BytesView>
2283 template <
typename Key,
typename Value,
typename BytesView>
2295 template <
typename Key,
typename Value,
typename BytesView>
2296 typename radix_tree<Key, Value, BytesView>::reverse_iterator
2299 return reverse_iterator(
end());
2308 template <
typename Key,
typename Value,
typename BytesView>
2309 typename radix_tree<Key, Value, BytesView>::reverse_iterator
2312 return reverse_iterator(
begin());
2320 template <
typename Key,
typename Value,
typename BytesView>
2321 typename radix_tree<Key, Value, BytesView>::const_reverse_iterator
2324 return const_reverse_iterator(
cend());
2333 template <
typename Key,
typename Value,
typename BytesView>
2334 typename radix_tree<Key, Value, BytesView>::const_reverse_iterator
2337 return const_reverse_iterator(
cbegin());
2340 template <
typename Key,
typename Value,
typename BytesView>
2341 typename radix_tree<Key, Value, BytesView>::const_reverse_iterator
2344 return const_reverse_iterator(
cend());
2347 template <
typename Key,
typename Value,
typename BytesView>
2348 typename radix_tree<Key, Value, BytesView>::const_reverse_iterator
2351 return const_reverse_iterator(
cbegin());
2354 template <
typename Key,
typename Value,
typename BytesView>
2356 radix_tree<Key, Value, BytesView>::print_rec(std::ostream &os,
2357 radix_tree::tagged_node_ptr n)
2360 os <<
"\"" << n.get_node() <<
"\""
2361 <<
" [style=filled,color=\"blue\"]" << std::endl;
2362 os <<
"\"" << n.get_node() <<
"\" [label=\"byte:" << n->byte
2363 <<
", bit:" << int(n->bit) <<
"\"]" << std::endl;
2365 auto parent = n->parent ? n->parent.get_node() : 0;
2366 os <<
"\"" << n.get_node() <<
"\" -> "
2367 <<
"\"" << parent <<
"\" [label=\"parent\"]" << std::endl;
2369 for (
auto it = n->begin(); it != n->end(); ++it) {
2373 auto ch = it->is_leaf() ? (
void *)it->get_leaf()
2374 : (
void *)it->get_node();
2376 os <<
"\"" << n.get_node() <<
"\" -> \"" << ch <<
"\""
2381 auto bv = bytes_view(n.get_leaf()->key());
2383 os <<
"\"" << n.get_leaf()
2384 <<
"\" [style=filled,color=\"green\"]" << std::endl;
2385 os <<
"\"" << n.get_leaf() <<
"\" [label=\"key:";
2387 for (
size_t i = 0; i < bv.size(); i++)
2390 os <<
"\"]" << std::endl;
2392 auto parent = n.get_leaf()->parent
2393 ? n.get_leaf()->parent.get_node()
2396 os <<
"\"" << n.get_leaf() <<
"\" -> \"" << parent
2397 <<
"\" [label=\"parent\"]" << std::endl;
2399 if (parent && n == parent->embedded_entry) {
2400 os <<
"{rank=same;\"" << parent <<
"\";\""
2401 << n.get_leaf() <<
"\"}" << std::endl;
2409 template <
typename K,
typename V,
typename BV>
2413 os <<
"digraph Radix {" << std::endl;
2418 os <<
"}" << std::endl;
2426 template <
typename Key,
typename Value,
typename BytesView>
2428 radix_tree<Key, Value, BytesView>::slice_index(
char b, uint8_t bit)
2430 return static_cast<unsigned>(b >> bit) & NIB;
2433 template <
typename Key,
typename Value,
typename BytesView>
2434 radix_tree<Key, Value, BytesView>::tagged_node_ptr::tagged_node_ptr(
2438 assert(!(
bool)*
this);
2441 template <
typename Key,
typename Value,
typename BytesView>
2442 radix_tree<Key, Value, BytesView>::tagged_node_ptr::tagged_node_ptr(
2443 const persistent_ptr<leaf> &ptr)
2444 : ptr(add_tag(ptr.
get()))
2446 assert(get_leaf() == ptr.get());
2449 template <
typename Key,
typename Value,
typename BytesView>
2450 radix_tree<Key, Value, BytesView>::tagged_node_ptr::tagged_node_ptr(
2451 const persistent_ptr<node> &ptr)
2454 assert(get_node() == ptr.get());
2457 template <
typename Key,
typename Value,
typename BytesView>
2458 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr &
2459 radix_tree<Key, Value, BytesView>::tagged_node_ptr::operator=(
2463 assert(!(
bool)*
this);
2468 template <
typename Key,
typename Value,
typename BytesView>
2469 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr &
2470 radix_tree<Key, Value, BytesView>::tagged_node_ptr::operator=(
2471 const persistent_ptr<leaf> &rhs)
2473 ptr = add_tag(rhs.get());
2474 assert(get_leaf() == rhs.get());
2479 template <
typename Key,
typename Value,
typename BytesView>
2480 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr &
2481 radix_tree<Key, Value, BytesView>::tagged_node_ptr::operator=(
2482 const persistent_ptr<node> &rhs)
2485 assert(get_node() == rhs.get());
2490 template <
typename Key,
typename Value,
typename BytesView>
2493 const radix_tree::tagged_node_ptr &rhs)
const
2495 return ptr.to_byte_pointer() == rhs.ptr.to_byte_pointer();
2498 template <
typename Key,
typename Value,
typename BytesView>
2501 const radix_tree::tagged_node_ptr &rhs)
const
2503 return !(*
this == rhs);
2506 template <
typename Key,
typename Value,
typename BytesView>
2509 const radix_tree::leaf *rhs)
const
2511 return is_leaf() && get_leaf() == rhs;
2514 template <
typename Key,
typename Value,
typename BytesView>
2517 const radix_tree::leaf *rhs)
const
2519 return !(*
this == rhs);
2522 template <
typename Key,
typename Value,
typename BytesView>
2529 template <
typename Key,
typename Value,
typename BytesView>
2531 radix_tree<Key, Value, BytesView>::tagged_node_ptr::add_tag(
2532 radix_tree::leaf *ptr)
const
2534 auto tagged =
reinterpret_cast<uintptr_t
>(ptr) | uintptr_t(IS_LEAF);
2535 return reinterpret_cast<radix_tree::leaf *
>(tagged);
2538 template <
typename Key,
typename Value,
typename BytesView>
2540 radix_tree<Key, Value, BytesView>::tagged_node_ptr::remove_tag(
void *ptr)
const
2542 auto untagged =
reinterpret_cast<uintptr_t
>(ptr) & ~uintptr_t(IS_LEAF);
2543 return reinterpret_cast<void *
>(untagged);
2546 template <
typename Key,
typename Value,
typename BytesView>
2548 radix_tree<Key, Value, BytesView>::tagged_node_ptr::is_leaf()
const
2550 auto value =
reinterpret_cast<uintptr_t
>(ptr.to_void_pointer());
2551 return value & uintptr_t(IS_LEAF);
2554 template <
typename Key,
typename Value,
typename BytesView>
2555 typename radix_tree<Key, Value, BytesView>::leaf *
2556 radix_tree<Key, Value, BytesView>::tagged_node_ptr::get_leaf()
const
2559 return static_cast<radix_tree::leaf *
>(
2560 remove_tag(ptr.to_void_pointer()));
2563 template <
typename Key,
typename Value,
typename BytesView>
2564 typename radix_tree<Key, Value, BytesView>::node *
2565 radix_tree<Key, Value, BytesView>::tagged_node_ptr::get_node()
const
2568 return static_cast<radix_tree::node *
>(ptr.to_void_pointer());
2571 template <
typename Key,
typename Value,
typename BytesView>
2572 radix_tree<Key, Value, BytesView>::tagged_node_ptr::operator bool() const
2575 return remove_tag(ptr.to_void_pointer()) !=
nullptr;
2578 template <
typename Key,
typename Value,
typename BytesView>
2579 typename radix_tree<Key, Value, BytesView>::node *
2580 radix_tree<Key, Value, BytesView>::tagged_node_ptr::operator->() const
2586 template <
typename Key,
typename Value,
typename BytesView>
2587 radix_tree<Key, Value, BytesView>::node::forward_iterator::forward_iterator(
2588 pointer child,
const node *n)
2589 : child(child), n(n)
2593 template <
typename Key,
typename Value,
typename BytesView>
2594 typename radix_tree<Key, Value, BytesView>::node::forward_iterator
2597 if (child == &n->embedded_entry)
2598 child = &n->child[0];
2605 template <
typename Key,
typename Value,
typename BytesView>
2606 radix_tree<Key, Value, BytesView>::node::node(tagged_node_ptr parent,
2607 byten_t
byte, bitn_t bit)
2608 : parent(parent), byte(byte), bit(bit)
2612 template <
typename Key,
typename Value,
typename BytesView>
2613 typename radix_tree<Key, Value, BytesView>::node::forward_iterator
2616 if (child == &n->child[0])
2617 child = &n->embedded_entry;
2624 template <
typename Key,
typename Value,
typename BytesView>
2625 typename radix_tree<Key, Value, BytesView>::node::forward_iterator
2628 forward_iterator tmp(child, n);
2633 template <
typename Key,
typename Value,
typename BytesView>
2634 typename radix_tree<Key, Value, BytesView>::node::forward_iterator::reference
2635 radix_tree<Key, Value, BytesView>::node::forward_iterator::operator*()
2641 template <
typename Key,
typename Value,
typename BytesView>
2642 typename radix_tree<Key, Value, BytesView>::node::forward_iterator::pointer
2643 radix_tree<Key, Value, BytesView>::node::forward_iterator::operator->()
2649 template <
typename Key,
typename Value,
typename BytesView>
2650 typename radix_tree<Key, Value, BytesView>::node::forward_iterator::pointer
2651 radix_tree<Key, Value, BytesView>::node::forward_iterator::get_node()
const
2656 template <
typename Key,
typename Value,
typename BytesView>
2659 const forward_iterator &rhs)
const
2661 return child == rhs.child && n == rhs.n;
2664 template <
typename Key,
typename Value,
typename BytesView>
2667 const forward_iterator &rhs)
const
2669 return child != rhs.child || n != rhs.n;
2672 template <
typename Key,
typename Value,
typename BytesView>
2673 template <
bool Direction>
2674 typename std::enable_if<
2676 radix_tree<Key, Value, BytesView>::node::direction::Forward,
2677 typename radix_tree<Key, Value,
2678 BytesView>::node::forward_iterator>::type
2681 return forward_iterator(&embedded_entry,
this);
2684 template <
typename Key,
typename Value,
typename BytesView>
2685 template <
bool Direction>
2686 typename std::enable_if<
2688 radix_tree<Key, Value, BytesView>::node::direction::Forward,
2689 typename radix_tree<Key, Value,
2690 BytesView>::node::forward_iterator>::type
2693 return forward_iterator(&child[SLNODES],
this);
2696 template <
typename Key,
typename Value,
typename BytesView>
2697 template <
bool Direction>
2698 typename std::enable_if<
2700 radix_tree<Key, Value, BytesView>::node::direction::Reverse,
2701 typename radix_tree<Key, Value,
2702 BytesView>::node::reverse_iterator>::type
2705 return reverse_iterator(end<direction::Forward>());
2708 template <
typename Key,
typename Value,
typename BytesView>
2709 template <
bool Direction>
2710 typename std::enable_if<
2712 radix_tree<Key, Value, BytesView>::node::direction::Reverse,
2713 typename radix_tree<Key, Value,
2714 BytesView>::node::reverse_iterator>::type
2717 return reverse_iterator(begin<direction::Forward>());
2720 template <
typename Key,
typename Value,
typename BytesView>
2721 template <
bool Direction,
typename Ptr>
2722 typename radix_tree<Key, Value, BytesView>::node::template iterator<Direction>
2723 radix_tree<Key, Value, BytesView>::node::find_child(
const Ptr &n)
const
2725 return std::find(begin<Direction>(), end<Direction>(), n);
2728 template <
typename Key,
typename Value,
typename BytesView>
2729 template <
bool Direction,
typename Enable>
2730 typename radix_tree<Key, Value, BytesView>::node::template iterator<Direction>
2731 radix_tree<Key, Value, BytesView>::node::make_iterator(
2732 const tagged_node_ptr *ptr)
const
2734 return forward_iterator(ptr,
this);
2737 template <
typename Key,
typename Value,
typename BytesView>
2738 template <
bool IsConst>
2739 radix_tree<Key, Value, BytesView>::radix_tree_iterator<
2740 IsConst>::radix_tree_iterator(leaf_ptr leaf_, node_ptr root)
2741 : leaf_(leaf_), root(root)
2745 template <
typename Key,
typename Value,
typename BytesView>
2746 template <
bool IsConst>
2747 template <
bool C,
typename Enable>
2748 radix_tree<Key, Value, BytesView>::radix_tree_iterator<
2749 IsConst>::radix_tree_iterator(
const radix_tree_iterator<false> &rhs)
2754 template <
typename Key,
typename Value,
typename BytesView>
2755 template <
bool IsConst>
2756 typename radix_tree<Key, Value,
2757 BytesView>::template radix_tree_iterator<IsConst>::reference
2758 radix_tree<Key, Value,
2759 BytesView>::radix_tree_iterator<IsConst>::operator*()
const
2765 template <
typename Key,
typename Value,
typename BytesView>
2766 template <
bool IsConst>
2767 typename radix_tree<Key, Value,
2768 BytesView>::template radix_tree_iterator<IsConst>::pointer
2769 radix_tree<Key, Value,
2770 BytesView>::radix_tree_iterator<IsConst>::operator->()
const
2785 template <
typename Key,
typename Value,
typename BytesView>
2786 template <
bool IsConst>
2787 template <
typename V,
typename Enable>
2792 auto pop =
pool_base(pmemobj_pool_by_ptr(leaf_));
2794 if (rhs.
size() <= leaf_->value().capacity()) {
2797 tagged_node_ptr *slot;
2799 if (!leaf_->parent) {
2800 assert(root->get_leaf() == leaf_);
2803 slot =
const_cast<tagged_node_ptr *
>(
2804 &*leaf_->parent->find_child(leaf_));
2807 auto old_leaf = leaf_;
2810 *slot = leaf::make_key_args(old_leaf->parent,
2811 old_leaf->key(), rhs);
2812 delete_persistent<typename radix_tree::leaf>(old_leaf);
2815 leaf_ = slot->get_leaf();
2824 template <
typename Key,
typename Value,
typename BytesView>
2825 template <
bool IsConst>
2826 template <
typename T,
typename V,
typename Enable>
2831 auto pop =
pool_base(pmemobj_pool_by_ptr(leaf_));
2834 [&] { leaf_->value() = std::forward<T>(rhs); });
2837 template <
typename Key,
typename Value,
typename BytesView>
2838 template <
bool IsConst>
2849 auto it = leaf_->parent->template find_child<
2850 radix_tree::node::direction::Forward>(leaf_);
2852 leaf_ =
const_cast<leaf_ptr
>(
2853 next_leaf<radix_tree::node::direction::Forward>(
2854 it, leaf_->parent));
2860 template <
typename Key,
typename Value,
typename BytesView>
2861 template <
bool IsConst>
2862 typename radix_tree<Key, Value,
2863 BytesView>::template radix_tree_iterator<IsConst> &
2868 leaf_ =
const_cast<leaf_ptr
>(
2869 radix_tree::find_leaf<
2870 radix_tree::node::direction::Reverse>(*root));
2873 assert(leaf_->parent);
2875 auto it = leaf_->parent->template find_child<
2876 radix_tree::node::direction::Reverse>(leaf_);
2878 leaf_ =
const_cast<leaf_ptr
>(
2879 next_leaf<radix_tree::node::direction::Reverse>(
2880 it, leaf_->parent));
2886 template <
typename Key,
typename Value,
typename BytesView>
2887 template <
bool IsConst>
2888 typename radix_tree<Key, Value,
2889 BytesView>::template radix_tree_iterator<IsConst>
2899 template <
typename Key,
typename Value,
typename BytesView>
2900 template <
bool IsConst>
2901 typename radix_tree<Key, Value,
2902 BytesView>::template radix_tree_iterator<IsConst>
2912 template <
typename Key,
typename Value,
typename BytesView>
2913 template <
bool IsConst>
2917 const radix_tree_iterator<C> &rhs)
const
2919 return leaf_ != rhs.leaf_;
2922 template <
typename Key,
typename Value,
typename BytesView>
2923 template <
bool IsConst>
2927 const radix_tree_iterator<C> &rhs)
const
2929 return !(*
this != rhs);
2937 template <
typename Key,
typename Value,
typename BytesView>
2938 template <
bool Direction,
typename Iterator>
2939 typename radix_tree<Key, Value, BytesView>::leaf *
2940 radix_tree<Key, Value, BytesView>::next_leaf(Iterator node,
2941 tagged_node_ptr parent)
2945 }
while (node != parent->template end<Direction>() && !(*node));
2948 if (node == parent->template end<Direction>()) {
2949 auto p = parent->parent;
2953 auto p_it = p->template find_child<Direction>(parent);
2954 return next_leaf<Direction>(p_it, p);
2957 return find_leaf<Direction>(*node);
2964 template <
typename Key,
typename Value,
typename BytesView>
2965 template <
bool Direction>
2966 typename radix_tree<Key, Value, BytesView>::leaf *
2967 radix_tree<Key, Value, BytesView>::find_leaf(
2968 typename radix_tree<Key, Value, BytesView>::tagged_node_ptr n)
2973 return n.get_leaf();
2975 for (
auto it = n->template begin<Direction>();
2976 it != n->template end<Direction>(); ++it) {
2978 return find_leaf<Direction>(*it);
2985 template <
typename Key,
typename Value,
typename BytesView>
2987 radix_tree<Key, Value, BytesView>::leaf::key()
2989 return *
reinterpret_cast<Key *
>(
this + 1);
2992 template <
typename Key,
typename Value,
typename BytesView>
2994 radix_tree<Key, Value, BytesView>::leaf::value()
2996 auto key_dst =
reinterpret_cast<char *
>(
this + 1);
2997 auto val_dst =
reinterpret_cast<Value *
>(
2998 key_dst + total_sizeof<Key>::value(key()));
3000 return *
reinterpret_cast<Value *
>(val_dst);
3003 template <
typename Key,
typename Value,
typename BytesView>
3005 radix_tree<Key, Value, BytesView>::leaf::key()
const
3007 return *
reinterpret_cast<const Key *
>(
this + 1);
3010 template <
typename Key,
typename Value,
typename BytesView>
3012 radix_tree<Key, Value, BytesView>::leaf::value()
const
3014 auto key_dst =
reinterpret_cast<const char *
>(
this + 1);
3015 auto val_dst =
reinterpret_cast<const Value *
>(
3016 key_dst + total_sizeof<Key>::value(key()));
3018 return *
reinterpret_cast<const Value *
>(val_dst);
3021 template <
typename Key,
typename Value,
typename BytesView>
3022 radix_tree<Key, Value, BytesView>::leaf::~leaf()
3024 detail::destroy<Key>(key());
3025 detail::destroy<Value>(value());
3028 template <
typename Key,
typename Value,
typename BytesView>
3029 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3030 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent)
3032 auto t = std::make_tuple();
3033 return make(parent, std::piecewise_construct, t, t,
3034 typename detail::make_index_sequence<>::type{},
3035 typename detail::make_index_sequence<>::type{});
3038 template <
typename Key,
typename Value,
typename BytesView>
3039 template <
typename... Args1,
typename... Args2>
3040 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3041 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3042 std::piecewise_construct_t pc,
3043 std::tuple<Args1...> first_args,
3044 std::tuple<Args2...> second_args)
3046 return make(parent, pc, first_args, second_args,
3047 typename detail::make_index_sequence<Args1...>::type{},
3048 typename detail::make_index_sequence<Args2...>::type{});
3051 template <
typename Key,
typename Value,
typename BytesView>
3052 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3053 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3054 const Key &k,
const Value &v)
3056 return make(parent, std::piecewise_construct, std::forward_as_tuple(k),
3057 std::forward_as_tuple(v));
3060 template <
typename Key,
typename Value,
typename BytesView>
3061 template <
typename K,
typename V>
3062 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3063 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent, K &&k,
3066 return make(parent, std::piecewise_construct,
3067 std::forward_as_tuple(std::forward<K>(k)),
3068 std::forward_as_tuple(std::forward<V>(v)));
3071 template <
typename Key,
typename Value,
typename BytesView>
3072 template <
typename K,
typename... Args>
3073 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3074 radix_tree<Key, Value, BytesView>::leaf::make_key_args(tagged_node_ptr parent,
3075 K &&k, Args &&... args)
3077 return make(parent, std::piecewise_construct,
3078 std::forward_as_tuple(std::forward<K>(k)),
3079 std::forward_as_tuple(std::forward<Args>(args)...));
3082 template <
typename Key,
typename Value,
typename BytesView>
3083 template <
typename K,
typename V>
3084 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3085 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3086 detail::pair<K, V> &&p)
3088 return make(parent, std::piecewise_construct,
3089 std::forward_as_tuple(std::move(p.first)),
3090 std::forward_as_tuple(std::move(p.second)));
3093 template <
typename Key,
typename Value,
typename BytesView>
3094 template <
typename K,
typename V>
3095 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3096 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3097 const detail::pair<K, V> &p)
3099 return make(parent, std::piecewise_construct,
3100 std::forward_as_tuple(p.first),
3101 std::forward_as_tuple(p.second));
3104 template <
typename Key,
typename Value,
typename BytesView>
3105 template <
typename K,
typename V>
3106 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3107 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3108 std::pair<K, V> &&p)
3110 return make(parent, std::piecewise_construct,
3111 std::forward_as_tuple(std::move(p.first)),
3112 std::forward_as_tuple(std::move(p.second)));
3115 template <
typename Key,
typename Value,
typename BytesView>
3116 template <
typename K,
typename V>
3117 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3118 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3119 const std::pair<K, V> &p)
3121 return make(parent, std::piecewise_construct,
3122 std::forward_as_tuple(p.first),
3123 std::forward_as_tuple(p.second));
3126 template <
typename Key,
typename Value,
typename BytesView>
3127 template <
typename... Args1,
typename... Args2,
size_t... I1,
size_t... I2>
3128 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3129 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3130 std::piecewise_construct_t,
3131 std::tuple<Args1...> &first_args,
3132 std::tuple<Args2...> &second_args,
3133 detail::index_sequence<I1...>,
3134 detail::index_sequence<I2...>)
3136 standard_alloc_policy<void> a;
3137 auto key_size = total_sizeof<Key>::value(std::get<I1>(first_args)...);
3139 total_sizeof<Value>::value(std::get<I2>(second_args)...);
3140 auto ptr =
static_cast<persistent_ptr<leaf>
>(
3141 a.allocate(
sizeof(leaf) + key_size + val_size));
3143 auto key_dst =
reinterpret_cast<Key *
>(ptr.get() + 1);
3144 auto val_dst =
reinterpret_cast<Value *
>(
3145 reinterpret_cast<char *
>(key_dst) + key_size);
3147 new (ptr.get()) leaf();
3148 new (key_dst) Key(std::forward<Args1>(std::get<I1>(first_args))...);
3149 new (val_dst) Value(std::forward<Args2>(std::get<I2>(second_args))...);
3151 ptr->parent = parent;
3156 template <
typename Key,
typename Value,
typename BytesView>
3157 persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3158 radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3161 return make(parent, other.key(), other.value());
3170 template <
typename Key,
typename Value,
typename BytesView>
3174 if (
nullptr == pmemobj_pool_by_ptr(
this))
3185 template <
typename Key,
typename Value,
typename BytesView>
3189 if (pmemobj_tx_stage() != TX_STAGE_WORK)
3191 "Function called out of transaction scope.");
3197 template <
typename Key,
typename Value,
typename BytesView>
3213 struct is_string : std::false_type {
3216 template <
typename CharT,
typename Traits>
3217 struct is_string<obj::basic_string<CharT, Traits>> : std::true_type {
3220 template <
typename CharT,
typename Traits>
3221 struct is_string<obj::experimental::basic_inline_string<CharT, Traits>>
3225 template <
typename T>
3226 struct bytes_view<T, typename std::enable_if<is_string<T>::value>::type> {
3227 using CharT =
typename T::value_type;
3228 using Traits =
typename T::traits_type;
3232 typename Enable =
typename std::enable_if<std::is_constructible<
3233 obj::basic_string_view<CharT, Traits>, C>::value>::type>
3234 bytes_view(
const C *s) : s(*s)
3238 char operator[](std::size_t p)
const
3240 return reinterpret_cast<const char *
>(s.data())[p];
3246 return s.size() *
sizeof(CharT);
3249 obj::basic_string_view<CharT, Traits> s;
3251 using is_transparent = void;
3254 template <
typename T>
3255 struct bytes_view<T,
3256 typename std::enable_if<std::is_integral<T>::value &&
3257 !std::is_signed<T>::value>::type> {
3258 bytes_view(
const T *k) : k(k)
3260 #if __cpp_lib_endian
3262 std::endian::native == std::endian::little,
3263 "Scalar type are not little endian on this platform!");
3264 #elif !defined(NDEBUG)
3266 uint16_t word = (2 << 8) + 1;
3267 assert(((
char *)&word)[0] == 1);
3271 char operator[](std::size_t p)
const
3273 return reinterpret_cast<const char *
>(k)[size() - p - 1];