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

Commit ed0e48c

Browse files
committed
inline_string: do not check if inline_string is on pmem
In pmemkv we have a use for keeping inline_string in DRAM. It's also safe (unlike for e.g. pmem::obj::string) since inline_string does not manage allocations.
1 parent 4808295 commit ed0e48c

2 files changed

Lines changed: 37 additions & 60 deletions

File tree

include/libpmemobj++/experimental/inline_string.hpp

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: BSD-3-Clause
2-
/* Copyright 2020, Intel Corporation */
2+
/* Copyright 2020-2021, Intel Corporation */
33

44
/**
55
* @file
@@ -30,6 +30,9 @@ namespace experimental
3030
* This class serves similar purpose to pmem::obj::string, but
3131
* keeps the data within the same allocation as inline_string itself.
3232
*
33+
* Unlike other containers, it can be used on pmem and dram. Modifiers (like
34+
* assign()) can only be called if inline string is kept on pmem).
35+
*
3336
* The data is always kept right after the inline_string structure.
3437
* It means that creating an object of inline_string must be done
3538
* as follows:
@@ -97,50 +100,35 @@ using inline_u32string = basic_inline_string<char32_t>;
97100

98101
/**
99102
* Constructs inline string from a string_view.
100-
*
101-
* @throw pool_error if inline_string doesn't reside on pmem.
102103
*/
103104
template <typename CharT, typename Traits>
104105
basic_inline_string<CharT, Traits>::basic_inline_string(
105106
basic_string_view<CharT, Traits> v)
106107
: size_(v.size()), capacity_(v.size())
107108
{
108-
if (nullptr == pmemobj_pool_by_ptr(this))
109-
throw pmem::pool_error("Invalid pool handle.");
110-
111109
std::copy(v.data(), v.data() + static_cast<ptrdiff_t>(size_), data());
112110

113111
data()[static_cast<ptrdiff_t>(size_)] = '\0';
114112
}
115113

116114
/**
117115
* Constructs empty inline_string with specified capacity.
118-
*
119-
* @throw pool_error if inline_string doesn't reside on pmem.
120116
*/
121117
template <typename CharT, typename Traits>
122118
basic_inline_string<CharT, Traits>::basic_inline_string(size_type capacity)
123119
: size_(0), capacity_(capacity)
124120
{
125-
if (nullptr == pmemobj_pool_by_ptr(this))
126-
throw pmem::pool_error("Invalid pool handle.");
127-
128121
data()[static_cast<ptrdiff_t>(size_)] = '\0';
129122
}
130123

131124
/**
132125
* Copy constructor
133-
*
134-
* @throw pool_error if inline_string doesn't reside on pmem.
135126
*/
136127
template <typename CharT, typename Traits>
137128
basic_inline_string<CharT, Traits>::basic_inline_string(
138129
const basic_inline_string &rhs)
139130
: size_(rhs.size()), capacity_(rhs.capacity())
140131
{
141-
if (nullptr == pmemobj_pool_by_ptr(this))
142-
throw pmem::pool_error("Invalid pool handle.");
143-
144132
std::copy(rhs.data(), rhs.data() + static_cast<ptrdiff_t>(size_),
145133
data());
146134

@@ -366,12 +354,17 @@ basic_inline_string<CharT, Traits>::snapshotted_data(size_t p, size_t n)
366354
* Transactionally assign content of basic_string_view.
367355
*
368356
* @throw std::out_of_range if rhs is larger than capacity.
357+
* @throw pool_error if inline string is not on pmem.
369358
*/
370359
template <typename CharT, typename Traits>
371360
basic_inline_string<CharT, Traits> &
372361
basic_inline_string<CharT, Traits>::assign(basic_string_view<CharT, Traits> rhs)
373362
{
374-
auto pop = obj::pool_base(pmemobj_pool_by_ptr(this));
363+
auto cpop = pmemobj_pool_by_ptr(this);
364+
if (nullptr == cpop)
365+
throw pmem::pool_error("Invalid pool handle.");
366+
367+
auto pop = pool_base(cpop);
375368

376369
if (rhs.size() > capacity())
377370
throw std::out_of_range("inline_string capacity exceeded.");

tests/inline_string/inline_string.cpp

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: BSD-3-Clause
2-
/* Copyright 2016-2020, Intel Corporation */
2+
/* Copyright 2016-2021, Intel Corporation */
33

44
#include "unittest.hpp"
55

@@ -247,59 +247,43 @@ test_inline_string(nvobj::pool<struct root<T>> &pop)
247247
});
248248
}
249249

250+
/* test if inline_string can be placed on dram */
250251
template <typename T>
251252
void
252-
test_ctor_exception_nopmem(nvobj::pool<struct root<T>> &pop)
253+
test_dram(nvobj::pool<struct root<T>> &pop)
253254
{
254-
auto bs1 = std::basic_string<T>(4, static_cast<T>('a'));
255-
nvobj::basic_string_view<T> bsv_test_string1(bs1.data(), bs1.length());
255+
using string_type = nvobj::experimental::basic_inline_string<T>;
256256

257-
try {
258-
std::string example_str("example");
259-
std::basic_string<T> bs(example_str.begin(), example_str.end());
260-
Object<T> o(
261-
1, nvobj::basic_string_view<T>(bs.data(), bs.length()));
262-
UT_ASSERT(0);
263-
} catch (pmem::pool_error &) {
264-
} catch (...) {
265-
UT_ASSERT(0);
266-
}
257+
constexpr size_t string_size = 20;
258+
typename std::aligned_storage<sizeof(string_type) +
259+
(string_size + 1) * sizeof(T),
260+
alignof(string_type)>::type buffer;
267261

268-
auto r = pop.root();
262+
std::basic_string<T> s(string_size, T('a'));
269263

270-
const auto req_capacity = 100;
264+
auto dram_location = reinterpret_cast<string_type *>(&buffer);
265+
new (dram_location)
266+
string_type(nvobj::basic_string_view<T>(s.data(), s.length()));
271267

272-
nvobj::transaction::run(pop, [&] {
273-
nvobj::standard_alloc_policy<void> allocator;
274-
r->o1 = static_cast<nvobj::persistent_ptr<Object<T>>>(
275-
allocator.allocate(sizeof(Object<T>) +
276-
req_capacity * sizeof(T)));
268+
UT_ASSERT(nvobj::basic_string_view<T>(s.data(), s.length()) ==
269+
nvobj::basic_string_view<T>(*dram_location));
277270

278-
new (r->o1.get()) Object<T>(1, bsv_test_string1);
271+
dram_location->~string_type();
279272

280-
try {
281-
Object<T> o(*r->o1);
282-
UT_ASSERT(0);
283-
} catch (pmem::pool_error &) {
284-
} catch (...) {
285-
UT_ASSERT(0);
286-
}
287-
});
288-
}
273+
new (dram_location) string_type(string_size);
289274

290-
template <typename T>
291-
void
292-
test_ctor_exception(void)
293-
{
275+
UT_ASSERTeq(dram_location->capacity(), string_size);
276+
UT_ASSERTeq(dram_location->size(), 0);
277+
278+
/* inline_string cannot be modified on dram. */
294279
try {
295-
int capacity = 10;
296-
nvobjex::basic_inline_string<T>(
297-
static_cast<nvobjex::inline_string::size_type>(
298-
capacity));
299-
UT_ASSERT(0);
280+
s = std::basic_string<T>(string_size / 2, T('b'));
281+
dram_location->assign(s.data());
282+
283+
ASSERT_UNREACHABLE;
300284
} catch (pmem::pool_error &) {
301285
} catch (...) {
302-
UT_ASSERT(0);
286+
ASSERT_UNREACHABLE;
303287
}
304288
}
305289
}
@@ -324,8 +308,8 @@ test(int argc, char *argv[])
324308
}
325309

326310
test_inline_string<T>(pop);
327-
test_ctor_exception_nopmem<T>(pop);
328-
test_ctor_exception<T>();
311+
test_dram<T>(pop);
312+
329313
pop.close();
330314
}
331315

0 commit comments

Comments
 (0)