8#include "hires_utc_clock.hpp"
10#include "algorithm.hpp"
11#include "type_traits.hpp"
12#include "concepts.hpp"
45 using callback_type =
typename notifier_type::callback_type;
46 using callback_ptr_type =
typename notifier_type::callback_ptr_type;
66 [[nodiscard]]
virtual value_type
load() const noexcept = 0;
76 virtual
bool store(value_type const &new_value) noexcept = 0;
78 void notify() noexcept
81 ttlet listeners = _listeners;
85 for (ttlet &listener : listeners) {
102 ttlet listeners = _listeners;
110 ttlet lock = std::scoped_lock(_mutex);
111 _listeners.push_back(listener);
114 void remove_listener(observable_base *listener)
117 ttlet lock = std::scoped_lock(_mutex);
118 std::erase(_listeners, listener);
122 mutable unfair_mutex _mutex;
123 observable<value_type> *_owner;
130 other->_owner = std::exchange(_owner,
nullptr);
132 for (
auto listener : listeners) {
142 using value_type =
typename super::value_type;
144 static constexpr bool is_atomic = may_be_atomic_v<value_type>;
145 using atomic_type = std::conditional_t<is_atomic, std::atomic<value_type>, value_type>;
151 value_type
load() const noexcept
override
156 bool store(value_type
const &new_value)
noexcept override
158 ttlet changed = _store(new_value);
168 value_type _load() const noexcept requires(
is_atomic)
170 return _value.load();
173 bool _store(value_type
const &new_value)
noexcept requires(
is_atomic)
175 if constexpr (std::equality_comparable<T>) {
176 ttlet old_value = _value.exchange(new_value);
177 if (old_value != new_value) {
184 _value.store(new_value);
189 value_type _load() const noexcept requires(not is_atomic)
191 ttlet
lock = std::scoped_lock(this->_mutex);
195 bool _store(value_type
const &new_value)
noexcept requires(not is_atomic)
197 ttlet
lock = std::scoped_lock(this->_mutex);
198 if constexpr (std::equality_comparable<T>) {
199 return std::exchange(_value, new_value) != new_value;
213 using value_type =
typename super::value_type;
217 if (
auto operand = _operand.load()) {
218 operand->remove_listener(
this);
224 if (
auto operand_ = _operand.load()) {
225 operand_->add_listener(
this);
231 virtual value_type
load() const noexcept
override
233 if (
auto operand = _operand.load()) {
234 return operand->
load();
240 virtual bool store(value_type
const &new_value)
noexcept override
242 if (
auto operand = _operand.load()) {
243 return operand->
store(new_value);
255 if (_operand.compare_exchange_strong(from, to)) {
256 from->remove_listener(
this);
258 to->add_listener(
this);
282 using value_type = T;
284 using callback_type =
typename notifier_type::callback_type;
285 using callback_ptr_type =
typename notifier_type::callback_ptr_type;
294 tt_axiom(&other !=
this);
295 tt_axiom(other.pimpl);
296 pimpl->replace_with(other.pimpl.get());
303 tt_axiom(other.pimpl);
304 pimpl->replace_with(other.pimpl.get());
318 tt_return_on_self_assignment(other);
319 tt_axiom(other.pimpl);
320 auto new_pimpl = std::make_unique<detail::observable_chain<value_type>>(
this, other.pimpl.get());
322 pimpl->replace_with(new_pimpl.get());
330 observable() noexcept : pimpl(
std::make_unique<detail::observable_value<value_type>>(this))
345 explicit operator bool() const noexcept
347 return static_cast<bool>(
load());
398 [[nodiscard]] value_type
load() const noexcept
401 return pimpl->load();
413 return pimpl->load();
424 bool store(value_type
const &new_value)
noexcept
427 return pimpl->store(new_value);
441 template<
typename Callback>
442 requires(std::is_invocable_v<Callback>) [[nodiscard]] callback_ptr_type
subscribe(Callback &&callback)
noexcept
444 auto callback_ptr =
notifier.subscribe(std::forward<Callback>(callback));
459 callback_ptr_type
subscribe(callback_ptr_type
const &callback)
noexcept
461 return notifier.subscribe(callback);
470 return notifier.unsubscribe(callback_ptr);
523 return *lhs <=> *rhs;
615 void notify() const noexcept
621 using pimpl_type = detail::observable_base<value_type>;
623 notifier_type notifier;
626 friend class detail::observable_base<value_type>;
640 using type =
typename observable<T>::value_type;
644using observable_argument_t =
typename observable_argument<T>::type;
An observable value.
Definition observable.hpp:280
observable(value_type const &value) noexcept
Construct a observable holding value.
Definition observable.hpp:338
friend auto operator<=>(observable const &lhs, value_type const &rhs) noexcept
Compare and observable with a value.
Definition observable.hpp:532
observable() noexcept
Default construct a observable holding a default constructed value.
Definition observable.hpp:330
friend auto operator-(observable const &lhs, value_type const &rhs) noexcept
Subtract a value from an observable to a value.
Definition observable.hpp:598
observable & operator=(value_type const &value) noexcept
Assign a new value.
Definition observable.hpp:358
callback_ptr_type subscribe(callback_ptr_type const &callback) noexcept
Subscribe a callback function.
Definition observable.hpp:459
friend auto operator<=>(observable const &lhs, observable const &rhs) noexcept
Compare the value of two observables.
Definition observable.hpp:521
friend auto operator-(observable const &lhs, observable const &rhs) noexcept
Subtract the value of two observables.
Definition observable.hpp:587
friend auto operator+(observable const &lhs, observable const &rhs) noexcept
Add the value of two observables.
Definition observable.hpp:554
observable & operator-=(value_type const &value) noexcept
Inplace subtract a value.
Definition observable.hpp:386
observable & operator+=(value_type const &value) noexcept
Inplace add a value.
Definition observable.hpp:372
friend auto operator+(observable const &lhs, value_type const &rhs) noexcept
Add the value of observables to a value.
Definition observable.hpp:565
friend bool operator==(observable const &lhs, value_type const &rhs) noexcept
Compare and observable with a value.
Definition observable.hpp:499
value_type operator-() const noexcept
Negate and return the value.
Definition observable.hpp:477
friend bool operator==(value_type const &lhs, observable const &rhs) noexcept
Compare and observable with a value.
Definition observable.hpp:510
value_type load() const noexcept
Load the value.
Definition observable.hpp:398
void unsubscribe(callback_ptr_type const &callback_ptr) noexcept
Unsubscribe a callback function.
Definition observable.hpp:468
callback_ptr_type subscribe(Callback &&callback) noexcept
Subscribe a callback function.
Definition observable.hpp:442
value_type operator*() const noexcept
Load the value.
Definition observable.hpp:410
friend bool operator==(observable const &lhs, observable const &rhs) noexcept
Compare the value of two observables.
Definition observable.hpp:488
friend auto operator<=>(value_type const &lhs, observable const &rhs) noexcept
Compare and observable with a value.
Definition observable.hpp:543
bool store(value_type const &new_value) noexcept
Assign a new value.
Definition observable.hpp:424
friend auto operator+(value_type const &lhs, observable const &rhs) noexcept
Add the value of observables to a value.
Definition observable.hpp:576
friend auto operator-(value_type const &lhs, observable const &rhs) noexcept
Subtract an observable value from a value.
Definition observable.hpp:609
Observable abstract base class.
Definition observable.hpp:41
void replace_with(observable_base *other) noexcept
Let other take over the listeners and owner.
Definition observable.hpp:99
virtual void replace_operand(observable_base *from, observable_base *to) noexcept
Replace the operands.
Definition observable.hpp:95
virtual bool store(value_type const &new_value) noexcept=0
Set the value.
observable_base(observable< value_type > *owner) noexcept
Constructor.
Definition observable.hpp:60
virtual value_type load() const noexcept=0
Get the current value.
Definition observable.hpp:139
bool store(value_type const &new_value) noexcept override
Set the value.
Definition observable.hpp:156
value_type load() const noexcept override
Get the current value.
Definition observable.hpp:151
Definition observable.hpp:209
void replace_operand(base *from, base *to) noexcept override
Replace the operand.
Definition observable.hpp:252
virtual value_type load() const noexcept override
Get the current value.
Definition observable.hpp:231
virtual bool store(value_type const &new_value) noexcept override
Set the value.
Definition observable.hpp:240
The value_type of an observable from the constructor argument type.
Definition observable.hpp:634
Definition type_traits.hpp:194