2#ifndef LIBSBX_SIGNAL_COPY_ON_WRITE_HPP_
3#define LIBSBX_SIGNAL_COPY_ON_WRITE_HPP_
8namespace sbx::signals {
10template<
typename Type>
15 template<
typename... Args>
16 explicit payload(Args&&... args)
18 value{std::forward<Args>(args)...} { }
22 std::atomic<std::size_t> count;
27 template<
typename Other>
32 using value_type = Type;
35 : _payload{
new payload{}} { }
37 template<
typename Other>
38 requires (!std::is_same_v<std::decay_t<Other>,
copy_on_write>)
40 : _payload{
new payload{std::forward<Other>(other)}} { }
43 : _payload{other._payload} {
45 _payload->count.fetch_add(1, std::memory_order_relaxed);
50 : _payload{std::exchange(other._payload,
nullptr)} {}
59 _payload = other._payload;
62 _payload->count.fetch_add(1, std::memory_order_relaxed);
72 _payload = std::exchange(other._payload,
nullptr);
78 auto read()
const noexcept ->
const value_type& {
79 return _payload->value;
82 auto write() -> value_type& {
87 return _payload->value;
92 auto _release() ->
void {
93 if (_payload && _payload->count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
100 auto _is_unique()
const ->
bool {
101 return _payload->count == 1;
108template<
typename Type>
111 swap(lhs._payload, rhs._payload);
114template<
typename Type>
115auto cow_read(
const Type& value) ->
const Type& {
119template<
typename Type>
120auto cow_read(copy_on_write<Type>& value) ->
const Type& {
124template<
typename Type>
125auto cow_write(Type& value) -> Type& {
129template<
typename Type>
130auto cow_write(copy_on_write<Type>& value) -> Type& {
131 return value.write();
Definition: copy_on_write.hpp:11