7#include "unfair_mutex.hpp"
17namespace hi::inline v1 {
35 actual(std::exchange(other.actual,
nullptr)), old_value(std::exchange(other.old_value, {}))
42#if HI_BUILD_TYPE == HI_BT_DEBUG
44 actual->rw_count =
false;
46 if (old_value != actual->value) {
47 actual->notifier_owners();
51 actual = std::exchange(other.actual,
nullptr);
52 old_value = std::exchange(other.old_value, {});
55 constexpr proxy_type() noexcept : actual(
nullptr), old_value() {}
59#if HI_BUILD_TYPE == HI_BT_DEBUG
61 hi_assert(actual->ro_count == 0);
63 hi_assert(not std::exchange(actual->rw_count,
true));
70#if HI_BUILD_TYPE == HI_BT_DEBUG
72 actual->rw_count =
false;
74 if (old_value != actual->value) {
75 actual->notify_owners();
80 constexpr operator value_type &()
const noexcept
86 constexpr value_type *operator->()
const noexcept
92 constexpr value_type& operator*()
const noexcept
98 constexpr value_type *operator&()
const noexcept
105 value_type old_value;
111#if HI_BUILD_TYPE == HI_BT_DEBUG
113 hi_assert(actual->rw_count ==
false);
114 hi_assert(actual->ro_count != 0);
122#if HI_BUILD_TYPE == HI_BT_DEBUG
124 hi_assert(actual->rw_count ==
false);
125 hi_assert(actual->ro_count != 0);
132#if HI_BUILD_TYPE == HI_BT_DEBUG
134 hi_assert(actual->rw_count ==
false);
135 hi_assert(actual->ro_count != 0);
139 actual = other.actual;
140#if HI_BUILD_TYPE == HI_BT_DEBUG
142 hi_assert(actual->rw_count ==
false);
143 hi_assert(actual->ro_count != 0);
151#if HI_BUILD_TYPE == HI_BT_DEBUG
153 hi_assert(actual->rw_count ==
false);
154 hi_assert(actual->ro_count != 0);
158 actual = std::exchange(other.actual,
nullptr);
163#if HI_BUILD_TYPE == HI_BT_DEBUG
165 hi_assert(actual->rw_count ==
true);
166 hi_assert(actual->ro_count == 0);
167 actual->rw_count =
false;
175#if HI_BUILD_TYPE == HI_BT_DEBUG
177 hi_assert(actual->rw_count ==
false);
178 hi_assert(actual->ro_count != 0);
182 actual = std::exchange(other.actual,
nullptr);
183#if HI_BUILD_TYPE == HI_BT_DEBUG
185 hi_assert(actual->rw_count ==
true);
186 hi_assert(actual->ro_count == 0);
187 actual->rw_count =
false;
197#if HI_BUILD_TYPE == HI_BT_DEBUG
200 hi_assert(actual->rw_count ==
false);
208#if HI_BUILD_TYPE == HI_BT_DEBUG
210 hi_assert(actual->rw_count ==
false);
211 hi_assert(actual->ro_count != 0);
217 constexpr operator value_type
const &()
const noexcept
220 return actual->value;
223 constexpr value_type
const *operator->()
const noexcept
229 constexpr value_type
const& operator*()
const noexcept
232 return actual->value;
235 constexpr value_type
const *operator&()
const noexcept
246#if HI_BUILD_TYPE == HI_BT_DEBUG
248 bool rw_count =
false;
253 hi_axiom(owners.
empty());
262 observable_impl(std::convertible_to<value_type>
auto&& value) noexcept : value(
hi_forward(value)) {}
264 proxy_type proxy() noexcept
269 const_proxy_type const_proxy() noexcept
274 void notify_owners() const noexcept
276 for (
hilet& owner : owners) {
277 owner->_notifier(value);
298 hilet nr_erased = std::erase(owners, &owner);
299 hi_axiom(nr_erased == 1);
304 hi_axiom(not owners.
empty());
306 auto keep_this_alive = owners.
front()->_pimpl;
307 hilet values_are_same = keep_this_alive->value == new_impl->value;
309 for (
auto owner : owners) {
310 owner->_pimpl = new_impl;
311 new_impl->owners.push_back(owner);
312 if (not values_are_same) {
313 owner->_notifier(value);
361 using value_type = T;
366 using const_reference = value_type
const&;
368 using token_type = notifier_type::token_type;
369 using awaiter_type = notifier_type::awaiter_type;
373 _pimpl->remove_owner(*
this);
382 _pimpl->add_owner(*
this);
393 _pimpl->add_owner(*
this);
408 if (
this == &other or _pimpl == other._pimpl) {
413 _pimpl->reseat_owners(other._pimpl);
417 token_type subscribe(callback_flags flags, std::invocable<value_type>
auto&& callback)
noexcept
419 return _notifier.subscribe(flags,
hi_forward(callback));
422 token_type subscribe(std::invocable<value_type>
auto&& callback)
noexcept
424 return _notifier.subscribe(callback_flags::synchronous,
hi_forward(callback));
427 awaiter_type
operator co_await()
const noexcept
429 return _notifier.operator
co_await();
443 return _pimpl->const_proxy();
457 return _pimpl->const_proxy();
473 return _pimpl->proxy();
482 return *const_proxy();
493 return const_proxy();
500 observable(std::convertible_to<value_type>
auto&& value) noexcept : _pimpl(std::make_shared<impl_type>(
hi_forward(value)))
502 _pimpl->add_owner(*
this);
524 auto operator++() noexcept requires(requires(value_type a) { {++a}; })
536 auto operator--() noexcept requires(requires(value_type a) { {--a}; })
548 auto operator++(
int)
noexcept requires(
requires(value_type a) { {a++}; })
560 auto operator--(
int)
noexcept requires(
requires(value_type a) { {a--}; })
572 auto operator+=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a +=
hi_forward(b)}; })
584 auto operator-=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a -=
hi_forward(b)}; })
596 auto operator*=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a *=
hi_forward(b)}; })
608 auto operator/=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a /=
hi_forward(b)}; })
620 auto operator%=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a %=
hi_forward(b)}; })
632 auto operator&=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a &=
hi_forward(b)}; })
644 auto operator|=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a |=
hi_forward(b)}; })
656 auto operator^=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a ^=
hi_forward(b)}; })
686 notifier_type _notifier;
701 using type =
typename observable<T>::value_type;
705using observable_argument_t =
typename observable_argument<T>::type;
#define hilet
Invariant should be the default for variables.
Definition required.hpp:23
#define hi_forward(x)
Forward a value, based on the decltype of the value.
Definition required.hpp:29
auto operator*=(auto &&rhs) noexcept
Inplace multiply.
Definition observable.hpp:596
auto operator--(int) noexcept
Post decrement.
Definition observable.hpp:560
observable() noexcept
Construct an observable.
Definition observable.hpp:380
observable & operator=(observable const &other) noexcept
Chain with another observable.
Definition observable.hpp:406
auto operator>>=(auto &&rhs) noexcept
Inplace shift right.
Definition observable.hpp:680
auto operator--() noexcept
Pre decrement.
Definition observable.hpp:536
observable(std::convertible_to< value_type > auto &&value) noexcept
Construct an observable with its value set.
Definition observable.hpp:500
auto operator/=(auto &&rhs) noexcept
Inplace divide.
Definition observable.hpp:608
auto operator|=(auto &&rhs) noexcept
Inplace bitwise or.
Definition observable.hpp:644
proxy_type proxy() noexcept
proxy a writable reference to the shared-value.
Definition observable.hpp:470
auto operator++() noexcept
Pre increment.
Definition observable.hpp:524
auto operator&=(auto &&rhs) noexcept
Inplace bitwise and.
Definition observable.hpp:632
const_reference operator*() const noexcept
Dereference to the value.
Definition observable.hpp:480
auto operator%=(auto &&rhs) noexcept
Inplace remainder.
Definition observable.hpp:620
observable(observable const &other) noexcept
Construct an observable and chain it to another.
Definition observable.hpp:391
auto operator+=(auto &&rhs) noexcept
Inplace add.
Definition observable.hpp:572
const_proxy_type operator->() const noexcept
Member select.
Definition observable.hpp:491
auto operator^=(auto &&rhs) noexcept
Inplace bitwise xor.
Definition observable.hpp:656
const_proxy_type const_proxy() const noexcept
proxy a constant reference to the shared value.
Definition observable.hpp:440
auto operator-=(auto &&rhs) noexcept
Inplace subtract.
Definition observable.hpp:584
auto operator<<=(auto &&rhs) noexcept
Inplace shift left.
Definition observable.hpp:668
observable & operator=(std::convertible_to< value_type > auto &&value) noexcept
Assign a new value.
Definition observable.hpp:510
auto operator++(int) noexcept
Post increment.
Definition observable.hpp:548
proxy_type proxy() const noexcept
proxy a constant reference to the shared value.
Definition observable.hpp:454
The shared value, shared between observers.
Definition observable.hpp:26
void remove_owner(owner_type &owner) noexcept
Remove an observer as one of the owners of the shared-value.
Definition observable.hpp:296
void add_owner(owner_type &owner) noexcept
Add an observer as one of the owners of the shared-value.
Definition observable.hpp:285
Definition observable.hpp:30
Definition observable.hpp:108
The value_type of an observable from the constructor argument type.
Definition observable.hpp:695
Definition concepts.hpp:39