sandbox
Loading...
Searching...
No Matches
copy_on_write.hpp
1#ifndef LIBSBX_SIGNAL_COPY_ON_WRITE_HPP_
2#define LIBSBX_SIGNAL_COPY_ON_WRITE_HPP_
3
4#include <utility>
5#include <atomic>
6
7namespace sbx::signals {
8
9template<typename Type>
11
12 struct payload {
13
14 template<typename... Args>
15 explicit payload(Args&&... args)
16 : count{1},
17 value{std::forward<Args>(args)...} { }
18
19 ~payload() = default;
20
21 std::atomic<std::size_t> count;
22 Type value;
23
24 }; // struct payload
25
26 template<typename Other>
27 friend auto swap(copy_on_write<Other>& lhs, copy_on_write<Other>& rhs) noexcept -> void;
28
29public:
30
31 using value_type = Type;
32
34 : _payload{new payload{}} { }
35
36 template<typename Other>
37 requires (!std::is_same_v<std::decay_t<Other>, copy_on_write>)
38 explicit copy_on_write(Other&& other)
39 : _payload{new payload{std::forward<Other>(other)}} { }
40
41 copy_on_write(const copy_on_write& other) noexcept
42 : _payload{other._payload} {
43 ++_payload->count;
44 }
45
46 copy_on_write(copy_on_write&& other) noexcept
47 : _payload{std::exchange(other._payload, nullptr)} { }
48
50 if (_payload && (_payload->count == 0)) {
51 delete _payload;
52 }
53 }
54
55 auto operator=(const copy_on_write& other) noexcept -> copy_on_write& {
56 if (this != &other) {
57 *this = copy_on_write{other};
58 }
59
60 return *this;
61 }
62
63 auto operator=(copy_on_write&& other) noexcept -> copy_on_write& {
64 auto temp = std::move(other);
65 swap(*this, temp);
66
67 return *this;
68 }
69
70 auto read() const noexcept -> const value_type& {
71 return _payload->value;
72 }
73
74 auto write() -> value_type& {
75 if (!_is_unique()) {
76 *this = copy_on_write{read()};
77 }
78
79 return _payload->value;
80 }
81
82private:
83
84 auto _is_unique() const -> bool {
85 return _payload->count == 1;
86 }
87
88 payload* _payload;
89
90}; // class copy_on_write
91
92template<typename Type>
93inline auto swap(copy_on_write<Type>& lhs, copy_on_write<Type>& rhs) noexcept -> void {
94 using std::swap;
95 swap(lhs._payload, rhs._payload);
96}
97
98template<typename Type>
99auto cow_read(const Type& value) -> const Type& {
100 return value;
101}
102
103template<typename Type>
104auto cow_read(copy_on_write<Type>& value) -> const Type& {
105 return value.read();
106}
107
108template<typename Type>
109auto cow_write(Type& value) -> Type& {
110 return value;
111}
112
113template<typename Type>
114auto cow_write(copy_on_write<Type>& value) -> Type& {
115 return value.write();
116}
117
118} // namespace sbx::signals
119
120#endif // LIBSBX_SIGNAL_COPY_ON_WRITE_HPP_
Definition: copy_on_write.hpp:10