7#include "wfree_idle_count.hpp"
8#include "unfair_mutex.hpp"
14namespace hi::inline
v1 {
21template<
typename T,
typename Allocator = std::allocator<T>>
25 using allocator_type = Allocator;
32 constexpr rcu(allocator_type allocator = allocator_type{})
noexcept : _allocator(allocator) {}
35 rcu(rcu
const&) =
delete;
37 rcu& operator=(rcu
const&) =
delete;
38 rcu& operator=(rcu&&) =
delete;
59 value_type
const *
get() const noexcept
61 return _ptr.load(std::memory_order::acquire);
73#if defined(__alpha__) or defined(__alpha) or defined(_M_ALPHA)
74 return _ptr.load(std::memory_order::acquire);
76 return _ptr.load(std::memory_order::relaxed);
85 [[nodiscard]] uint64_t
version() const noexcept
96 hilet lock = std::scoped_lock(_old_ptrs_mutex);
97 return _old_ptrs.size() + not empty();
106 [[nodiscard]] value_type *
exchange(value_type *ptr)
noexcept
108 return _ptr.exchange(ptr, std::memory_order::release);
118 [[nodiscard]] value_type *
copy(value_type
const *ptr)
const noexcept
123 return std::launder(new_ptr);
132 [[nodiscard]] value_type *
copy() const noexcept
136 value_type
const *
const ptr = get();
140 return std::launder(new_ptr);
147 void abort(value_type *ptr)
const noexcept
160 auto *old_ptr = exchange(ptr);
161 auto old_version = version();
163 add_old_copy(old_version, old_ptr);
182 auto *
const old_ptr = exchange(new_ptr);
183 hilet old_version = version();
186 add_old_copy(old_version, old_ptr);
189 [[nodiscard]]
bool empty() const noexcept
191 return not to_bool(_ptr.load(std::memory_order::relaxed));
194 explicit operator bool() const noexcept
199 void reset() noexcept
202 auto *
const old_ptr = _ptr.exchange(
nullptr, std::memory_order::release);
203 hilet old_version = *_idle_count;
206 add_old_copy(old_version, old_ptr);
209 rcu& operator=(nullptr_t)
noexcept
230 hilet new_version = version();
232 hilet lock = std::scoped_lock(_old_ptrs_mutex);
233 _old_ptrs.emplace_back(old_version, old_ptr);
236 auto it = _old_ptrs.begin();
237 while (it != _old_ptrs.end() and it->first < new_version) {
242 _old_ptrs.erase(_old_ptrs.begin(), it);
249 mutable allocator_type _allocator;
#define hi_assert_not_null(x,...)
Assert if an expression is not nullptr.
Definition assert.hpp:118
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
#define hi_forward(x)
Forward a value, based on the decltype of the value.
Definition utility.hpp:29
DOXYGEN BUG.
Definition algorithm.hpp:15
Read-copy-update.
Definition rcu.hpp:22
constexpr rcu(allocator_type allocator=allocator_type{}) noexcept
Construct a new rcu object.
Definition rcu.hpp:32
void add_old_copy(uint64_t old_version, value_type *old_ptr) noexcept
Add an old copy.
Definition rcu.hpp:224
void unlock() const noexcept
Unlock the rcu pointer for reading.
Definition rcu.hpp:49
void commit(value_type *ptr) noexcept
Commit the copied value.
Definition rcu.hpp:157
value_type * copy() const noexcept
Create a copy of the value.
Definition rcu.hpp:132
value_type const * get() const noexcept
get the rcu-pointer.
Definition rcu.hpp:59
void lock() const noexcept
Lock the rcu pointer for reading.
Definition rcu.hpp:42
value_type * exchange(value_type *ptr) noexcept
Exchange the rcu-pointers.
Definition rcu.hpp:106
value_type const * unsafe_get() noexcept
get the rcu-pointer.
Definition rcu.hpp:71
void emplace(auto &&...args) noexcept
Emplace a new value.
Definition rcu.hpp:176
size_t capacity() const noexcept
Number of objects that are currently allocated.
Definition rcu.hpp:94
uint64_t version() const noexcept
The version of the lock.
Definition rcu.hpp:85
void abort(value_type *ptr) const noexcept
Abort a copy.
Definition rcu.hpp:147
value_type * copy(value_type const *ptr) const noexcept
Create a copy of the value at the given pointer.
Definition rcu.hpp:118
Counts how many times a critical section was idle.
Definition wfree_idle_count.hpp:39