Skip to content
This repository was archived by the owner on Mar 22, 2023. It is now read-only.

Commit c68618e

Browse files
Merge pull request #942 from igchor/stable_1.11_radix_fix
Fix radix_tree::try_emplace
2 parents eb1bc68 + fca1e54 commit c68618e

File tree

2 files changed

+132
-90
lines changed

2 files changed

+132
-90
lines changed

include/libpmemobj++/experimental/radix_tree.hpp

Lines changed: 99 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -411,46 +411,46 @@ struct radix_tree<Key, Value, BytesView>::leaf {
411411
const Key &key() const;
412412
const Value &value() const;
413413

414-
private:
415-
friend class radix_tree<Key, Value, BytesView>;
416-
417-
leaf() = default;
418-
419-
template <typename... Args>
420-
static persistent_ptr<leaf> make(tagged_node_ptr parent,
421-
Args &&... args);
422-
423-
static persistent_ptr<leaf> make_internal();
414+
static persistent_ptr<leaf> make(tagged_node_ptr parent);
424415

425416
template <typename... Args1, typename... Args2>
426417
static persistent_ptr<leaf>
427-
make_internal(std::piecewise_construct_t pc,
428-
std::tuple<Args1...> first_args,
429-
std::tuple<Args2...> second_args);
430-
431-
template <typename K, typename V>
432-
static persistent_ptr<leaf> make_internal(K &&k, V &&v);
418+
make(tagged_node_ptr parent, std::piecewise_construct_t pc,
419+
std::tuple<Args1...> first_args, std::tuple<Args2...> second_args);
433420
template <typename K, typename V>
434-
static persistent_ptr<leaf> make_internal(const K &k, const V &v);
435-
421+
static persistent_ptr<leaf> make(tagged_node_ptr parent, K &&k, V &&v);
422+
static persistent_ptr<leaf> make(tagged_node_ptr parent, const Key &k,
423+
const Value &v);
424+
template <typename K, typename... Args>
425+
static persistent_ptr<leaf> make_key_args(tagged_node_ptr parent, K &&k,
426+
Args &&... args);
436427
template <typename K, typename V>
437-
static persistent_ptr<leaf> make_internal(detail::pair<K, V> &&p);
428+
static persistent_ptr<leaf> make(tagged_node_ptr parent,
429+
detail::pair<K, V> &&p);
438430
template <typename K, typename V>
439-
static persistent_ptr<leaf> make_internal(const detail::pair<K, V> &p);
440-
431+
static persistent_ptr<leaf> make(tagged_node_ptr parent,
432+
const detail::pair<K, V> &p);
441433
template <typename K, typename V>
442-
static persistent_ptr<leaf> make_internal(std::pair<K, V> &&p);
434+
static persistent_ptr<leaf> make(tagged_node_ptr parent,
435+
std::pair<K, V> &&p);
443436
template <typename K, typename V>
444-
static persistent_ptr<leaf> make_internal(const std::pair<K, V> &p);
437+
static persistent_ptr<leaf> make(tagged_node_ptr parent,
438+
const std::pair<K, V> &p);
439+
static persistent_ptr<leaf> make(tagged_node_ptr parent,
440+
const leaf &other);
441+
442+
private:
443+
friend class radix_tree<Key, Value, BytesView>;
444+
445+
leaf() = default;
445446

446447
template <typename... Args1, typename... Args2, size_t... I1,
447448
size_t... I2>
448-
static persistent_ptr<leaf> make_internal(
449-
std::piecewise_construct_t, std::tuple<Args1...> &first_args,
450-
std::tuple<Args2...> &second_args,
451-
detail::index_sequence<I1...>, detail::index_sequence<I2...>);
452-
453-
static persistent_ptr<leaf> make_internal(const leaf &other);
449+
static persistent_ptr<leaf>
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...>);
454454

455455
tagged_node_ptr parent = nullptr;
456456
};
@@ -1294,7 +1294,8 @@ radix_tree<Key, Value, BytesView>::try_emplace(const key_type &k,
12941294
{
12951295
return internal_emplace(k, [&](tagged_node_ptr parent) {
12961296
size_++;
1297-
return leaf::make(parent, k, std::forward<Args>(args)...);
1297+
return leaf::make_key_args(parent, k,
1298+
std::forward<Args>(args)...);
12981299
});
12991300
}
13001301

@@ -1489,8 +1490,8 @@ radix_tree<Key, Value, BytesView>::try_emplace(key_type &&k, Args &&... args)
14891490
{
14901491
return internal_emplace(k, [&](tagged_node_ptr parent) {
14911492
size_++;
1492-
return leaf::make(parent, std::move(k),
1493-
std::forward<Args>(args)...);
1493+
return leaf::make_key_args(parent, std::move(k),
1494+
std::forward<Args>(args)...);
14941495
});
14951496
}
14961497

@@ -1536,8 +1537,8 @@ radix_tree<Key, Value, BytesView>::try_emplace(K &&k, Args &&... args) ->
15361537
{
15371538
return internal_emplace(k, [&](tagged_node_ptr parent) {
15381539
size_++;
1539-
return leaf::make(parent, std::forward<K>(k),
1540-
std::forward<Args>(args)...);
1540+
return leaf::make_key_args(parent, std::forward<K>(k),
1541+
std::forward<Args>(args)...);
15411542
});
15421543
}
15431544

@@ -2799,8 +2800,8 @@ radix_tree<Key, Value, BytesView>::radix_tree_iterator<IsConst>::assign_val(
27992800
auto old_leaf = leaf_;
28002801

28012802
transaction::run(pop, [&] {
2802-
*slot = leaf::make(old_leaf->parent, old_leaf->key(),
2803-
rhs);
2803+
*slot = leaf::make_key_args(old_leaf->parent,
2804+
old_leaf->key(), rhs);
28042805
delete_persistent<typename radix_tree::leaf>(old_leaf);
28052806
});
28062807

@@ -2973,18 +2974,6 @@ radix_tree<Key, Value, BytesView>::find_leaf(
29732974
std::abort();
29742975
}
29752976

2976-
template <typename Key, typename Value, typename BytesView>
2977-
template <typename... Args>
2978-
persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
2979-
radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
2980-
Args &&... args)
2981-
{
2982-
auto ptr = make_internal(std::forward<Args>(args)...);
2983-
ptr->parent = parent;
2984-
2985-
return ptr;
2986-
}
2987-
29882977
template <typename Key, typename Value, typename BytesView>
29892978
Key &
29902979
radix_tree<Key, Value, BytesView>::leaf::key()
@@ -3030,94 +3019,111 @@ radix_tree<Key, Value, BytesView>::leaf::~leaf()
30303019

30313020
template <typename Key, typename Value, typename BytesView>
30323021
persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3033-
radix_tree<Key, Value, BytesView>::leaf::make_internal()
3022+
radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent)
30343023
{
30353024
auto t = std::make_tuple();
3036-
return make_internal(std::piecewise_construct, t, t,
3037-
typename detail::make_index_sequence<>::type{},
3038-
typename detail::make_index_sequence<>::type{});
3025+
return make(parent, std::piecewise_construct, t, t,
3026+
typename detail::make_index_sequence<>::type{},
3027+
typename detail::make_index_sequence<>::type{});
30393028
}
30403029

30413030
template <typename Key, typename Value, typename BytesView>
30423031
template <typename... Args1, typename... Args2>
30433032
persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3044-
radix_tree<Key, Value, BytesView>::leaf::make_internal(
3045-
std::piecewise_construct_t pc, std::tuple<Args1...> first_args,
3046-
std::tuple<Args2...> second_args)
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)
30473037
{
3048-
return make_internal(
3049-
pc, first_args, second_args,
3050-
typename detail::make_index_sequence<Args1...>::type{},
3051-
typename detail::make_index_sequence<Args2...>::type{});
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{});
30523041
}
30533042

30543043
template <typename Key, typename Value, typename BytesView>
3055-
template <typename K, typename V>
30563044
persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3057-
radix_tree<Key, Value, BytesView>::leaf::make_internal(K &&k, V &&v)
3045+
radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3046+
const Key &k, const Value &v)
30583047
{
3059-
return make_internal(std::piecewise_construct,
3060-
std::forward_as_tuple(std::forward<K>(k)),
3061-
std::forward_as_tuple(std::forward<V>(v)));
3048+
return make(parent, std::piecewise_construct, std::forward_as_tuple(k),
3049+
std::forward_as_tuple(v));
30623050
}
30633051

30643052
template <typename Key, typename Value, typename BytesView>
30653053
template <typename K, typename V>
30663054
persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3067-
radix_tree<Key, Value, BytesView>::leaf::make_internal(const K &k, const V &v)
3055+
radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent, K &&k,
3056+
V &&v)
3057+
{
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)));
3061+
}
3062+
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)
30683068
{
3069-
return make_internal(std::piecewise_construct, std::forward_as_tuple(k),
3070-
std::forward_as_tuple(v));
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)...));
30713072
}
30723073

30733074
template <typename Key, typename Value, typename BytesView>
30743075
template <typename K, typename V>
30753076
persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3076-
radix_tree<Key, Value, BytesView>::leaf::make_internal(detail::pair<K, V> &&p)
3077+
radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3078+
detail::pair<K, V> &&p)
30773079
{
3078-
return make_internal(std::piecewise_construct,
3079-
std::forward_as_tuple(std::forward<K>(p.first)),
3080-
std::forward_as_tuple(std::forward<V>(p.second)));
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)));
30813083
}
30823084

30833085
template <typename Key, typename Value, typename BytesView>
30843086
template <typename K, typename V>
30853087
persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3086-
radix_tree<Key, Value, BytesView>::leaf::make_internal(
3087-
const detail::pair<K, V> &p)
3088+
radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3089+
const detail::pair<K, V> &p)
30883090
{
3089-
return make_internal(std::piecewise_construct,
3090-
std::forward_as_tuple(p.first),
3091-
std::forward_as_tuple(p.second));
3091+
return make(parent, std::piecewise_construct,
3092+
std::forward_as_tuple(p.first),
3093+
std::forward_as_tuple(p.second));
30923094
}
30933095

30943096
template <typename Key, typename Value, typename BytesView>
30953097
template <typename K, typename V>
30963098
persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3097-
radix_tree<Key, Value, BytesView>::leaf::make_internal(std::pair<K, V> &&p)
3099+
radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3100+
std::pair<K, V> &&p)
30983101
{
3099-
return make_internal(std::piecewise_construct,
3100-
std::forward_as_tuple(std::forward<K>(p.first)),
3101-
std::forward_as_tuple(std::forward<V>(p.second)));
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)));
31023105
}
31033106

31043107
template <typename Key, typename Value, typename BytesView>
31053108
template <typename K, typename V>
31063109
persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3107-
radix_tree<Key, Value, BytesView>::leaf::make_internal(const std::pair<K, V> &p)
3110+
radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3111+
const std::pair<K, V> &p)
31083112
{
3109-
return make_internal(std::piecewise_construct,
3110-
std::forward_as_tuple(p.first),
3111-
std::forward_as_tuple(p.second));
3113+
return make(parent, std::piecewise_construct,
3114+
std::forward_as_tuple(p.first),
3115+
std::forward_as_tuple(p.second));
31123116
}
31133117

31143118
template <typename Key, typename Value, typename BytesView>
31153119
template <typename... Args1, typename... Args2, size_t... I1, size_t... I2>
31163120
persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3117-
radix_tree<Key, Value, BytesView>::leaf::make_internal(
3118-
std::piecewise_construct_t, std::tuple<Args1...> &first_args,
3119-
std::tuple<Args2...> &second_args, detail::index_sequence<I1...>,
3120-
detail::index_sequence<I2...>)
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...>)
31213127
{
31223128
standard_alloc_policy<void> a;
31233129
auto key_size = total_sizeof<Key>::value(std::get<I1>(first_args)...);
@@ -3134,14 +3140,17 @@ radix_tree<Key, Value, BytesView>::leaf::make_internal(
31343140
new (key_dst) Key(std::forward<Args1>(std::get<I1>(first_args))...);
31353141
new (val_dst) Value(std::forward<Args2>(std::get<I2>(second_args))...);
31363142

3143+
ptr->parent = parent;
3144+
31373145
return ptr;
31383146
}
31393147

31403148
template <typename Key, typename Value, typename BytesView>
31413149
persistent_ptr<typename radix_tree<Key, Value, BytesView>::leaf>
3142-
radix_tree<Key, Value, BytesView>::leaf::make_internal(const leaf &other)
3150+
radix_tree<Key, Value, BytesView>::leaf::make(tagged_node_ptr parent,
3151+
const leaf &other)
31433152
{
3144-
return make_internal(other.key(), other.value());
3153+
return make(parent, other.key(), other.value());
31453154
}
31463155

31473156
/**

tests/external/libcxx/map/map.modifiers/try.emplace.pass.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
// C++17
2929

3030
#include "../is_transparent.h"
31+
#include "helper_classes.hpp"
3132
#include "map_wrapper.hpp"
3233
#include "unittest.hpp"
3334

@@ -46,13 +47,16 @@ using container4 =
4647
container_t<nvobj::string, Moveable, TRANSPARENT_COMPARE_STRING>;
4748
using container5 =
4849
container_t<MoveableWrapper, MoveableWrapper, TRANSPARENT_COMPARE>;
50+
using container6 =
51+
container_t<int, default_constructible_only, TRANSPARENT_COMPARE>;
4952

5053
struct root {
5154
nvobj::persistent_ptr<container> s;
5255
nvobj::persistent_ptr<container2> s2;
5356
nvobj::persistent_ptr<container3> s3;
5457
nvobj::persistent_ptr<container4> s4;
5558
nvobj::persistent_ptr<container5> s5;
59+
nvobj::persistent_ptr<container6> s6;
5660
};
5761

5862
int
@@ -318,6 +322,35 @@ run(pmem::obj::pool<root> &pop)
318322
pmem::obj::transaction::run(
319323
pop, [&] { nvobj::delete_persistent<M>(robj->s5); });
320324
}
325+
{
326+
typedef container6 M;
327+
typedef std::pair<M::iterator, bool> R;
328+
pmem::obj::transaction::run(
329+
pop, [&] { robj->s6 = nvobj::make_persistent<M>(); });
330+
auto &m = *robj->s6;
331+
R r;
332+
for (int i = 0; i < 20; i += 2)
333+
m.emplace(std::piecewise_construct,
334+
std::forward_as_tuple(i),
335+
std::forward_as_tuple());
336+
UT_ASSERT(m.size() == 10);
337+
UT_ASSERT(default_constructible_only::count == 10);
338+
339+
r = m.try_emplace(2);
340+
UT_ASSERT(m.size() == 10);
341+
UT_ASSERT(!r.second); // was not inserted
342+
UT_ASSERT(default_constructible_only::count == 10);
343+
UT_ASSERT(r.first->MAP_KEY == 2); // key
344+
345+
r = m.try_emplace(3);
346+
UT_ASSERT(m.size() == 11);
347+
UT_ASSERT(r.second); // was inserted
348+
UT_ASSERT(r.first->MAP_KEY == 3); // key
349+
UT_ASSERT(default_constructible_only::count == 11);
350+
pmem::obj::transaction::run(
351+
pop, [&] { nvobj::delete_persistent<M>(robj->s6); });
352+
}
353+
321354
return 0;
322355
}
323356

0 commit comments

Comments
 (0)