Skip to content
This repository was archived by the owner on Mar 22, 2023. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
7c6e8d9
Add code skeleton for new persistent-aware self_relative_ptr and swmr…
yjrobin Jul 9, 2021
0ec4b0d
Merge remote-tracking branch 'origin/master' into swmr_skip_list
yjrobin Jul 9, 2021
5e942eb
Add new pa_self_relative_ptr (persistent-aware self_relative_ptr) and…
yjrobin Jul 22, 2021
e4f4cc4
Add new pa_self_relative_ptr (persistent-aware self_relative_ptr) and…
yjrobin Jul 22, 2021
4e5a08b
Clear format
yjrobin Jul 22, 2021
2c30c74
Merge branch 'pmem:master' into master
yjrobin Jul 22, 2021
def1592
Clear format
yjrobin Jul 22, 2021
0ea98e7
Clear format
yjrobin Jul 22, 2021
ec1f1cc
Clear format
yjrobin Jul 22, 2021
51ee8aa
Clear format
yjrobin Jul 23, 2021
6af3575
Clear format
yjrobin Jul 23, 2021
1a3c8c0
Clear format
yjrobin Jul 23, 2021
08ddbfe
Fix copy constructor
yjrobin Jul 23, 2021
380c70f
Add some comments
yjrobin Jul 23, 2021
8226e94
Fix and add some comments.
yjrobin Jul 23, 2021
92d238d
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 23, 2021
f4eac57
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 23, 2021
7952c73
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 23, 2021
07d9e54
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 23, 2021
2879d1a
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 23, 2021
d5b38ac
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 23, 2021
783c3ab
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 23, 2021
54e7a63
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 24, 2021
cd406ba
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 24, 2021
cae1d74
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 24, 2021
f00194b
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 24, 2021
7690fe0
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 24, 2021
cf97885
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 24, 2021
6a37da5
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 24, 2021
e18e9da
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 24, 2021
b2fea9d
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 24, 2021
be7f84f
Merge remote-tracking branch 'upstream/master'
yjrobin Aug 24, 2021
627eaef
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 24, 2021
df944c8
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 24, 2021
dde768b
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 27, 2021
f087cc6
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 27, 2021
5442e77
Implement persistent-aware feature of self_relative_ptr as a template…
yjrobin Aug 27, 2021
ec0b540
Merge branch 'pmem:master' into master
yjrobin Sep 26, 2021
bdad6f7
Merge branch 'pmem:master' into master
yjrobin Oct 26, 2021
01064d7
Merge branch 'pmem-master'
yjrobin Oct 28, 2021
d561afd
Merge remote-tracking branch 'origin/master'
yjrobin Oct 28, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ option(TEST_SEGMENT_VECTOR_VECTOR_EXPSIZE "enable testing of pmem::obj::segment_
option(TEST_SEGMENT_VECTOR_VECTOR_FIXEDSIZE "enable testing of pmem::obj::segment_vector with vector as segment_vector_type and fixed_size_policy" ON)
option(TEST_ENUMERABLE_THREAD_SPECIFIC "enable testing of pmem::obj::enumerable_thread_specific" ON)
option(TEST_CONCURRENT_MAP "enable testing of pmem::obj::experimental::concurrent_map (depends on TEST_STRING)" ON)
option(TEST_SWMR_MAP "enable testing of pmem::obj::experimental::swmr_map (depends on TEST_STRING)" ON)
option(TEST_SELF_RELATIVE_POINTER "enable testing of pmem::obj::experimental::self_relative_ptr" ON)
option(TEST_RADIX_TREE "enable testing of pmem::obj::experimental::radix_tree" ON)
option(TEST_MPSC_QUEUE "enable testing of pmem::obj::experimental::mpsc_queue" ON)
Expand Down
306 changes: 306 additions & 0 deletions include/libpmemobj++/experimental/atomic_pa_self_relative_ptr.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
// SPDX-License-Identifier: BSD-3-Clause
/* Copyright 2021, 4Paradigm Inc. */

#ifndef LIBPMEMOBJ_CPP_ATOMIC_PA_SELF_RELATIVE_PTR_HPP
#define LIBPMEMOBJ_CPP_ATOMIC_PA_SELF_RELATIVE_PTR_HPP

#include <libpmemobj++/detail/common.hpp>
#include <libpmemobj++/detail/self_relative_ptr_base_impl.hpp>
#include <libpmemobj++/experimental/pa_self_relative_ptr.hpp>
#include <libpmemobj++/transaction.hpp>

#include <atomic>

namespace std
{
/**
* Atomic specialization for pa_self_relative_ptr
*
* Doesn't automatically add itself to the transaction.
* The user is responsible for persisting the data.
*/
template <typename T>
struct atomic<pmem::obj::experimental::pa_self_relative_ptr<T>> {
private:
using ptr_type = pmem::detail::self_relative_ptr_base_impl<
std::atomic<std::ptrdiff_t>>;
using accessor = pmem::detail::self_relative_accessor<
std::atomic<std::ptrdiff_t>>;

public:
using this_type = atomic;
using value_type = pmem::obj::experimental::pa_self_relative_ptr<T>;
using difference_type = typename value_type::difference_type;

/*
* Constructors
*/

constexpr atomic() noexcept = default;
atomic(value_type value) : ptr()
{
store(value);
}
atomic(const atomic &) = delete;

void
store(value_type desired,
std::memory_order order = std::memory_order_seq_cst) noexcept
{
auto offset = accessor::pointer_to_offset(ptr, desired.get());
LIBPMEMOBJ_CPP_ANNOTATE_HAPPENS_BEFORE(order, &ptr);
accessor::get_offset(ptr).store(
(offset & desired.flush_set_mask()), order);
}

value_type
load(std::memory_order order = std::memory_order_seq_cst) const noexcept
{
auto offset = accessor::get_offset(ptr).load(order);
LIBPMEMOBJ_CPP_ANNOTATE_HAPPENS_AFTER(order, &ptr);
auto pointer = accessor::offset_to_pointer<T>(
offset | ~(value_type::flush_set_mask(offset)), ptr);
return value_type{pointer, value_type::flush_needed(offset)};
}

value_type
exchange(value_type desired,
std::memory_order order = std::memory_order_seq_cst) noexcept
{
auto new_offset =
accessor::pointer_to_offset(ptr, desired.get());
auto old_offset = accessor::get_offset(ptr).exchange(
new_offset & desired.flush_set_mask(), order);
return value_type{accessor::offset_to_pointer<T>(
old_offset |
~(value_type::flush_set_mask(
old_offset)),
ptr),
value_type::flush_needed(old_offset)};
}

bool
compare_exchange_weak(value_type &expected, value_type desired,
std::memory_order success,
std::memory_order failure) noexcept
{
auto expected_offset =
accessor::pointer_to_offset(ptr, expected.get());
auto expected_actual =
expected_offset & expected.flush_set_mask();
auto desired_offset =
accessor::pointer_to_offset(ptr, desired.get());
auto desired_actual = desired_offset & desired.flush_set_mask();
bool result = accessor::get_offset(ptr).compare_exchange_weak(
expected_actual, desired_actual, success, failure);
if (!result) {
expected = value_type{
accessor::offset_to_pointer<T>(
expected_actual |
~(value_type::flush_set_mask(
expected_actual)),
ptr),
value_type::flush_needed(expected_actual)};
}
return result;
}

bool
compare_exchange_weak(
value_type &expected, value_type desired,
std::memory_order order = std::memory_order_seq_cst) noexcept
{
auto expected_offset =
accessor::pointer_to_offset(ptr, expected.get());
auto expected_actual =
expected_offset & expected.flush_set_mask();
auto desired_offset =
accessor::pointer_to_offset(ptr, desired.get());
auto desired_actual = desired_offset & desired.flush_set_mask();
bool result = accessor::get_offset(ptr).compare_exchange_weak(
expected_actual, desired_actual, order);
if (!result) {
expected = value_type{
accessor::offset_to_pointer<T>(
expected_actual |
~(value_type::flush_set_mask(
expected_actual)),
ptr),
value_type::flush_needed(expected_actual)};
}
return result;
}

bool
compare_exchange_strong(value_type &expected, value_type desired,
std::memory_order success,
std::memory_order failure) noexcept
{
auto expected_offset =
accessor::pointer_to_offset(ptr, expected.get());
auto expected_actual =
expected_offset & expected.flush_set_mask();
auto desired_offset =
accessor::pointer_to_offset(ptr, desired.get());
auto desired_actual = desired_offset & desired.flush_set_mask();
bool result = accessor::get_offset(ptr).compare_exchange_strong(
expected_actual, desired_actual, success, failure);
if (!result) {
expected = value_type{
accessor::offset_to_pointer<T>(
expected_actual |
~(value_type::flush_set_mask(
expected_actual)),
ptr),
value_type::flush_needed(expected_actual)};
}
return result;
}

bool
compare_exchange_strong(
value_type &expected, value_type desired,
std::memory_order order = std::memory_order_seq_cst) noexcept
{
auto expected_offset =
accessor::pointer_to_offset(ptr, expected.get());
auto expected_actual =
expected_offset & expected.flush_set_mask();
auto desired_offset =
accessor::pointer_to_offset(ptr, desired.get());
auto desired_actual = desired_offset & desired.flush_set_mask();
bool result = accessor::get_offset(ptr).compare_exchange_strong(
expected_actual, desired_actual, order);
if (!result) {
expected = value_type{
accessor::offset_to_pointer<T>(
expected_actual |
~(value_type::flush_set_mask(
expected_actual)),
ptr),
value_type::flush_needed(expected_actual)};
}
return result;
}

value_type
fetch_add(difference_type val,
std::memory_order order = std::memory_order_seq_cst) noexcept
{
auto offset = accessor::get_offset(ptr).fetch_add(
val * static_cast<difference_type>(sizeof(T)), order);
return value_type{
accessor::offset_to_pointer<T>(
offset | ~(value_type::flush_set_mask(offset)),
ptr),
value_type::flush_needed(offset)};
}

value_type
fetch_sub(difference_type val,
std::memory_order order = std::memory_order_seq_cst) noexcept
{
auto offset = accessor::get_offset(ptr).fetch_sub(
val * static_cast<difference_type>(sizeof(T)), order);
return value_type{
accessor::offset_to_pointer<T>(
offset | ~(value_type::flush_set_mask(offset)),
ptr),
value_type::flush_needed(offset)};
}

bool
is_lock_free() const noexcept
{
return accessor::get_offset(ptr).is_lock_free();
}

/*
* Operators
*/

operator value_type() const noexcept
{
return load();
}

atomic &operator=(const atomic &) = delete;
atomic &operator=(const atomic &) volatile = delete;

value_type
operator=(value_type desired) noexcept
{
store(desired);
return desired;
}

value_type
operator++() noexcept
{
return this->fetch_add(1) + 1;
}

value_type
operator++(int) noexcept
{
return this->fetch_add(1);
}

value_type
operator--() noexcept
{
return this->fetch_sub(1) - 1;
}

value_type
operator--(int) noexcept
{
return this->fetch_sub(1);
}

value_type
operator+=(difference_type diff) noexcept
{
return this->fetch_add(diff) + diff;
}

value_type
operator-=(difference_type diff) noexcept
{
return this->fetch_sub(diff) - diff;
}

private:
ptr_type ptr;
};

} /* namespace std */

namespace pmem
{

namespace detail
{

/**
* can_do_snapshot atomic specialization for pa_self_relative_ptr. Not thread
* safe.
*
* Use in a single threaded environment only.
*/
template <typename T>
struct can_do_snapshot<
std::atomic<obj::experimental::pa_self_relative_ptr<T>>> {
using snapshot_type = obj::experimental::pa_self_relative_ptr<T>;
static constexpr bool value = sizeof(std::atomic<snapshot_type>) ==
sizeof(typename snapshot_type::offset_type);
static_assert(
value,
"std::atomic<pa_self_relative_ptr> should be the same size");
};

} /* namespace detail */

} /* namespace pmem */

#endif
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: BSD-3-Clause
/* Copyright 2020-2021, Intel Corporation */
/* Copyright 2021, 4Paradigm Inc. */

#ifndef LIBPMEMOBJ_CPP_ATOMIC_SELF_RELATIVE_PTR_HPP
#define LIBPMEMOBJ_CPP_ATOMIC_SELF_RELATIVE_PTR_HPP
Expand Down
Loading