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

Commit 433d174

Browse files
authored
Merge pull request #1156 from lukaszstolarczuk/ext-radix
Extend radix_tree tests and disable operator-- (for MtMode)
2 parents 0ddba32 + 75d04ac commit 433d174

File tree

9 files changed

+778
-476
lines changed

9 files changed

+778
-476
lines changed

include/libpmemobj++/experimental/radix_tree.hpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ struct bytes_view;
9898
* swap() invalidates all references and iterators.
9999
*
100100
* MtMode enables single-writer multiple-readers concurrency with read
101-
* uncommitted isolation. In this, mode user HAS to call runtime_initialize_mt
101+
* uncommitted isolation. In this, mode user HAS TO call runtime_initialize_mt
102102
* after each application restart and runtime_finalize_mt before destroying
103103
* radix tree.
104104
*
105-
* This has the following effects:
105+
* Enabling MtMode has the following effects:
106106
* - erase and clear does not free nodes/leaves immediately, instead they are
107107
* added to a garbage list which can be freed by calling garbage_collect()
108108
* - insert_or_assign and iterator.assign_val do not perform an in-place update,
@@ -617,7 +617,9 @@ struct radix_tree<Key, Value, BytesView, MtMode>::radix_tree_iterator {
617617
value_type &>::type;
618618
using pointer = typename std::conditional<IsConst, value_type const *,
619619
value_type *>::type;
620-
using iterator_category = std::bidirectional_iterator_tag;
620+
using iterator_category = typename std::conditional<
621+
MtMode, std::forward_iterator_tag,
622+
std::bidirectional_iterator_tag>::type;
621623

622624
radix_tree_iterator() = default;
623625
radix_tree_iterator(leaf_ptr leaf_, tree_ptr tree);
@@ -646,9 +648,13 @@ struct radix_tree<Key, Value, BytesView, MtMode>::radix_tree_iterator {
646648
void assign_val(T &&rhs);
647649

648650
radix_tree_iterator &operator++();
651+
template <bool Mt = MtMode,
652+
typename Enable = typename std::enable_if<!Mt>::type>
649653
radix_tree_iterator &operator--();
650654

651655
radix_tree_iterator operator++(int);
656+
template <bool Mt = MtMode,
657+
typename Enable = typename std::enable_if<!Mt>::type>
652658
radix_tree_iterator operator--(int);
653659

654660
template <bool C>
@@ -3200,8 +3206,15 @@ radix_tree<Key, Value, BytesView,
32003206
return true;
32013207
}
32023208

3209+
/*
3210+
* If MtMode == true it's not safe to use this operator (iterator may end up
3211+
* invalid if concurrent erase happen).
3212+
* XXX: it's not enabled in MtMode due to:
3213+
* https://github.com/pmem/libpmemobj-cpp/issues/1159
3214+
*/
32033215
template <typename Key, typename Value, typename BytesView, bool MtMode>
32043216
template <bool IsConst>
3217+
template <bool Mt, typename Enable>
32053218
typename radix_tree<Key, Value, BytesView,
32063219
MtMode>::template radix_tree_iterator<IsConst> &
32073220
radix_tree<Key, Value, BytesView,
@@ -3278,8 +3291,15 @@ radix_tree<Key, Value, BytesView,
32783291
return tmp;
32793292
}
32803293

3294+
/*
3295+
* If MtMode == true it's not safe to use this operator (iterator may end up
3296+
* invalid if concurrent erase happen).
3297+
* XXX: it's not enabled in MtMode due to:
3298+
* https://github.com/pmem/libpmemobj-cpp/issues/1159
3299+
*/
32813300
template <typename Key, typename Value, typename BytesView, bool MtMode>
32823301
template <bool IsConst>
3302+
template <bool Mt, typename Enable>
32833303
typename radix_tree<Key, Value, BytesView,
32843304
MtMode>::template radix_tree_iterator<IsConst>
32853305
radix_tree<Key, Value, BytesView,

tests/radix_tree/radix.hpp

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,91 @@
11
// SPDX-License-Identifier: BSD-3-Clause
22
/* Copyright 2020-2021, Intel Corporation */
33

4+
#include <functional>
5+
#include <libpmemobj.h>
6+
#include <random>
7+
48
#include "transaction_helpers.hpp"
59
#include "unittest.hpp"
610

711
#include <libpmemobj++/experimental/inline_string.hpp>
812
#include <libpmemobj++/experimental/radix_tree.hpp>
913

10-
#include <functional>
11-
12-
#include <libpmemobj.h>
14+
static std::mt19937_64 generator;
1315

1416
namespace nvobj = pmem::obj;
1517
namespace nvobjex = pmem::obj::experimental;
1618

17-
using container_int =
19+
using cntr_int =
1820
nvobjex::radix_tree<nvobjex::inline_string, nvobj::p<unsigned>>;
19-
using container_string =
21+
using cntr_string =
2022
nvobjex::radix_tree<nvobjex::inline_string, nvobjex::inline_string>;
2123

22-
using container_int_int =
23-
nvobjex::radix_tree<unsigned, nvobj::p<unsigned>,
24-
nvobjex::bytes_view<unsigned>, false>;
25-
using container_int_string =
26-
nvobjex::radix_tree<unsigned, nvobjex::inline_string>;
24+
using cntr_int_int = nvobjex::radix_tree<unsigned, nvobj::p<unsigned>,
25+
nvobjex::bytes_view<unsigned>, false>;
26+
using cntr_int_string = nvobjex::radix_tree<unsigned, nvobjex::inline_string>;
2727

28-
using container_inline_s_wchart =
28+
using cntr_inline_s_wchart =
2929
nvobjex::radix_tree<nvobjex::basic_inline_string<wchar_t>,
3030
nvobj::p<unsigned>>;
31-
using container_inline_s_wchart_wchart =
31+
using cntr_inline_s_wchart_wchart =
3232
nvobjex::radix_tree<nvobjex::basic_inline_string<wchar_t>,
3333
nvobjex::basic_inline_string<wchar_t>>;
34-
using container_inline_s_u8t =
34+
using cntr_inline_s_u8t =
3535
nvobjex::radix_tree<nvobjex::basic_inline_string<uint8_t>,
3636
nvobjex::basic_inline_string<uint8_t>>;
3737

38-
using container_int_mt =
38+
using cntr_int_mt =
3939
nvobjex::radix_tree<nvobjex::inline_string, nvobj::p<unsigned>,
4040
nvobjex::bytes_view<nvobjex::inline_string>, true>;
41-
using container_string_mt =
41+
using cntr_string_mt =
4242
nvobjex::radix_tree<nvobjex::inline_string, nvobjex::inline_string,
4343
nvobjex::bytes_view<nvobjex::inline_string>, true>;
4444

45-
using container_int_int_mt =
45+
using cntr_int_int_mt =
4646
nvobjex::radix_tree<unsigned, nvobj::p<unsigned>,
4747
nvobjex::bytes_view<unsigned>, true>;
48-
using container_int_string_mt =
48+
using cntr_int_string_mt =
4949
nvobjex::radix_tree<unsigned, nvobjex::inline_string,
5050
nvobjex::bytes_view<unsigned>, true>;
5151

52-
using container_inline_s_wchart_mt = nvobjex::radix_tree<
52+
using cntr_inline_s_wchart_mt = nvobjex::radix_tree<
5353
nvobjex::basic_inline_string<wchar_t>, nvobj::p<unsigned>,
5454
nvobjex::bytes_view<nvobjex::basic_inline_string<wchar_t>>, true>;
55-
using container_inline_s_wchart_wchart_mt = nvobjex::radix_tree<
55+
using cntr_inline_s_wchart_wchart_mt = nvobjex::radix_tree<
5656
nvobjex::basic_inline_string<wchar_t>,
5757
nvobjex::basic_inline_string<wchar_t>,
5858
nvobjex::bytes_view<nvobjex::basic_inline_string<wchar_t>>, true>;
59-
using container_inline_s_u8t_mt = nvobjex::radix_tree<
59+
using cntr_inline_s_u8t_mt = nvobjex::radix_tree<
6060
nvobjex::basic_inline_string<uint8_t>,
6161
nvobjex::basic_inline_string<uint8_t>,
6262
nvobjex::bytes_view<nvobjex::basic_inline_string<uint8_t>>, true>;
6363

6464
struct root {
65-
nvobj::persistent_ptr<container_int> radix_int;
66-
nvobj::persistent_ptr<container_string> radix_str;
65+
nvobj::persistent_ptr<cntr_int> radix_int;
66+
nvobj::persistent_ptr<cntr_string> radix_str;
6767

68-
nvobj::persistent_ptr<container_int_int> radix_int_int;
69-
nvobj::persistent_ptr<container_int_string> radix_int_str;
68+
nvobj::persistent_ptr<cntr_int_int> radix_int_int;
69+
nvobj::persistent_ptr<cntr_int_string> radix_int_str;
7070

71-
nvobj::persistent_ptr<container_inline_s_wchart> radix_inline_s_wchart;
72-
nvobj::persistent_ptr<container_inline_s_wchart_wchart>
71+
nvobj::persistent_ptr<cntr_inline_s_wchart> radix_inline_s_wchart;
72+
nvobj::persistent_ptr<cntr_inline_s_wchart_wchart>
7373
radix_inline_s_wchart_wchart;
74-
nvobj::persistent_ptr<container_inline_s_u8t> radix_inline_s_u8t;
74+
nvobj::persistent_ptr<cntr_inline_s_u8t> radix_inline_s_u8t;
7575

76-
nvobj::persistent_ptr<container_int_mt> radix_int_mt;
77-
nvobj::persistent_ptr<container_string_mt> radix_str_mt;
76+
nvobj::persistent_ptr<cntr_int_mt> radix_int_mt;
77+
nvobj::persistent_ptr<cntr_string_mt> radix_str_mt;
7878

79-
nvobj::persistent_ptr<container_int_int_mt> radix_int_int_mt;
80-
nvobj::persistent_ptr<container_int_string_mt> radix_int_str_mt;
79+
nvobj::persistent_ptr<cntr_int_int_mt> radix_int_int_mt;
80+
nvobj::persistent_ptr<cntr_int_string_mt> radix_int_str_mt;
8181

82-
nvobj::persistent_ptr<container_inline_s_wchart_mt>
83-
radix_inline_s_wchart_mt;
84-
nvobj::persistent_ptr<container_inline_s_wchart_wchart_mt>
82+
nvobj::persistent_ptr<cntr_inline_s_wchart_mt> radix_inline_s_wchart_mt;
83+
nvobj::persistent_ptr<cntr_inline_s_wchart_wchart_mt>
8584
radix_inline_s_wchart_wchart_mt;
86-
nvobj::persistent_ptr<container_inline_s_u8t_mt> radix_inline_s_u8t_mt;
85+
nvobj::persistent_ptr<cntr_inline_s_u8t_mt> radix_inline_s_u8t_mt;
8786
};
8887

88+
/* Helper functions to access key/value of different types */
8989
template <typename Container,
9090
typename Enable = typename std::enable_if<
9191
std::is_same<typename Container::mapped_type,
@@ -108,9 +108,9 @@ value(unsigned v, int repeats = 1)
108108
{
109109
using CharT = typename Container::mapped_type::value_type;
110110

111+
auto str = std::to_string(v);
111112
auto s = std::basic_string<CharT>{};
112113
for (int i = 0; i < repeats; i++) {
113-
auto str = std::to_string(v);
114114
s += std::basic_string<CharT>(str.begin(), str.end());
115115
}
116116

@@ -178,6 +178,7 @@ operator!=(pmem::obj::experimental::basic_inline_string<CharT, Traits> &lhs,
178178
.compare(rhs) != 0;
179179
}
180180

181+
/* verify all elements in container, using lower_/upper_bound and find */
181182
template <typename Container, typename K, typename F>
182183
void
183184
verify_elements(nvobj::persistent_ptr<Container> ptr, unsigned count, K &&key_f,
@@ -216,6 +217,8 @@ verify_elements(nvobj::persistent_ptr<Container> ptr, unsigned count, K &&key_f,
216217
}
217218
}
218219

220+
/* run 1 thread with modifications (erase/write/etc.) and multiple threads with
221+
* reads */
219222
template <typename ModifyF, typename ReadF>
220223
static void
221224
parallel_modify_read(ModifyF modifier, std::vector<ReadF> &readers,
@@ -230,16 +233,30 @@ parallel_modify_read(ModifyF modifier, std::vector<ReadF> &readers,
230233
});
231234
}
232235

236+
/* each test suite should initialize generator at the beginning */
237+
void
238+
init_random()
239+
{
240+
std::random_device rd;
241+
auto seed = rd();
242+
std::cout << "rand seed: " << seed << std::endl;
243+
generator = std::mt19937_64(seed);
244+
}
245+
233246
template <typename Container>
234247
static void
235248
init_container(nvobj::pool<root> &pop, nvobj::persistent_ptr<Container> &ptr,
236-
const size_t initial_elements, const size_t value_repeats = 1)
249+
const size_t initial_elements, const size_t value_repeats = 1,
250+
bool rand_keys = false)
237251
{
238252
nvobj::transaction::run(
239253
pop, [&] { ptr = nvobj::make_persistent<Container>(); });
240254

241255
for (size_t i = 0; i < initial_elements; ++i) {
242-
ptr->emplace(key<Container>(i),
243-
value<Container>(i, value_repeats));
256+
auto k = key<Container>(i);
257+
if (rand_keys) {
258+
k = key<Container>(static_cast<unsigned>(generator()));
259+
}
260+
ptr->emplace(k, value<Container>(i, value_repeats));
244261
}
245262
}

0 commit comments

Comments
 (0)