17#ifndef STLAB_COPY_ON_WRITE_HPP
18#define STLAB_COPY_ON_WRITE_HPP
106 std::atomic<std::size_t> _count{1};
108 model()
noexcept(std::is_nothrow_constructible_v<T>) =
default;
110 template <
class... Args>
111 explicit model(Args&&... args)
noexcept(std::is_nothrow_constructible_v<T, Args&&...>) :
112 _value(std::forward<Args>(args)...) {}
120 using disable_copy = std::enable_if_t<!std::is_same_v<std::decay_t<U>,
copy_on_write>>*;
122 template <
typename U>
123 using disable_copy_assign =
126 auto default_model()
noexcept(std::is_nothrow_constructible_v<T>) -> model* {
127 static model default_s;
146 _self = default_model();
149 _self->_count.fetch_add(1, std::memory_order_relaxed);
156 copy_on_write(U&& x, disable_copy<U> =
nullptr) : _self(new model(std::forward<U>(x))) {}
161 template <
class U,
class V,
class... Args>
163 _self(new model(std::forward<U>(x), std::forward<V>(y), std::forward<Args>(args)...)) {}
169 assert(_self &&
"FATAL (sparent) : using a moved copy_on_write object");
172 _self->_count.fetch_add(1, std::memory_order_relaxed);
179 assert(_self &&
"WARNING (sparent) : using a moved copy_on_write object");
183 assert(!_self || ((_self->_count > 0) &&
"FATAL (sparent) : double delete"));
184 if (_self && (_self->_count.fetch_sub(1, std::memory_order_release) == 1)) {
185 std::atomic_thread_fence(std::memory_order_acquire);
186 if constexpr (std::is_default_constructible_v<element_type>) {
187 assert(_self != default_model());
198 assert(
this != &x &&
"self-assignment is not allowed");
206 auto tmp{std::move(x)};
217 _self->_value = std::forward<U>(x);
233 return _self->_value;
248 template <
class Transform,
class Inplace>
250 static_assert(std::is_invocable_r_v<T, Transform, const T&>,
251 "Transform must be invocable with const T&");
252 static_assert(std::is_invocable_r_v<void, Inplace, T&>,
253 "Inplace must be invocable with T&");
258 inplace(_self->_value);
261 return _self->_value;
268 assert(_self &&
"FATAL (sparent) : using a moved copy_on_write object");
270 return _self->_value;
293 [[nodiscard]]
auto unique() const noexcept ->
bool {
294 assert(_self &&
"FATAL (sparent) : using a moved copy_on_write object");
296 return _self->_count.load(std::memory_order_acquire) == 1;
309 assert((_self && x._self) &&
"FATAL (sparent) : using a moved copy_on_write object");
311 return _self == x._self;
318 std::swap(x._self, y._self);
326 return !x.identity(y) && (*x < *y);
374 return x.identity(y) || (*x == *y);
T element_type
Definition copy_on_write.hpp:140
friend void swap(copy_on_write &x, copy_on_write &y) noexcept
Definition copy_on_write.hpp:317
friend auto operator<(const element_type &x, const copy_on_write &y) noexcept -> bool
Definition copy_on_write.hpp:333
copy_on_write(U &&x, V &&y, Args &&... args)
Definition copy_on_write.hpp:162
auto operator=(copy_on_write &&x) noexcept -> copy_on_write &
Definition copy_on_write.hpp:205
auto write(Transform transform, Inplace inplace) -> element_type &
Definition copy_on_write.hpp:249
friend auto operator!=(const element_type &x, const copy_on_write &y) noexcept -> bool
Definition copy_on_write.hpp:393
copy_on_write(U &&x, disable_copy< U >=nullptr)
Definition copy_on_write.hpp:156
friend auto operator<(const copy_on_write &x, const copy_on_write &y) noexcept -> bool
Definition copy_on_write.hpp:325
T value_type
Definition copy_on_write.hpp:135
auto operator=(const copy_on_write &x) noexcept -> copy_on_write &
Definition copy_on_write.hpp:196
friend auto operator>=(const copy_on_write &x, const copy_on_write &y) noexcept -> bool
Definition copy_on_write.hpp:361
auto operator*() const noexcept -> const element_type &
Definition copy_on_write.hpp:281
auto identity(const copy_on_write &x) const noexcept -> bool
Definition copy_on_write.hpp:308
friend auto operator<=(const element_type &x, const copy_on_write &y) noexcept -> bool
Definition copy_on_write.hpp:357
auto read() const noexcept -> const element_type &
Definition copy_on_write.hpp:267
friend auto operator!=(const copy_on_write &x, const element_type &y) noexcept -> bool
Definition copy_on_write.hpp:389
friend auto operator>=(const element_type &x, const copy_on_write &y) noexcept -> bool
Definition copy_on_write.hpp:369
friend auto operator==(const copy_on_write &x, const copy_on_write &y) noexcept -> bool
Definition copy_on_write.hpp:373
friend auto operator<(const copy_on_write &x, const element_type &y) noexcept -> bool
Definition copy_on_write.hpp:329
auto unique_instance() const noexcept -> bool
Definition copy_on_write.hpp:303
friend auto operator>=(const copy_on_write &x, const element_type &y) noexcept -> bool
Definition copy_on_write.hpp:365
auto operator->() const noexcept -> const element_type *
Definition copy_on_write.hpp:286
friend auto operator<=(const copy_on_write &x, const element_type &y) noexcept -> bool
Definition copy_on_write.hpp:353
copy_on_write() noexcept(std::is_nothrow_constructible_v< T >)
Definition copy_on_write.hpp:145
auto unique() const noexcept -> bool
Definition copy_on_write.hpp:293
auto write() -> element_type &
Definition copy_on_write.hpp:230
friend auto operator>(const copy_on_write &x, const copy_on_write &y) noexcept -> bool
Definition copy_on_write.hpp:337
friend auto operator>(const element_type &x, const copy_on_write &y) noexcept -> bool
Definition copy_on_write.hpp:345
friend auto operator<=(const copy_on_write &x, const copy_on_write &y) noexcept -> bool
Definition copy_on_write.hpp:349
auto operator=(U &&x) -> disable_copy_assign< U >
Definition copy_on_write.hpp:215
friend auto operator!=(const copy_on_write &x, const copy_on_write &y) noexcept -> bool
Definition copy_on_write.hpp:385
copy_on_write(const copy_on_write &x) noexcept
Definition copy_on_write.hpp:168
friend auto operator==(const copy_on_write &x, const element_type &y) noexcept -> bool
Definition copy_on_write.hpp:377
friend auto operator==(const element_type &x, const copy_on_write &y) noexcept -> bool
Definition copy_on_write.hpp:381
friend auto operator>(const copy_on_write &x, const element_type &y) noexcept -> bool
Definition copy_on_write.hpp:341
copy_on_write(copy_on_write &&x) noexcept
Definition copy_on_write.hpp:178
Definition copy_on_write.hpp:91