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;
308 for (
auto owner : owners) {
309 owner->_pimpl = new_impl;
310 new_impl->owners.push_back(owner);
311 owner->_notifier(value);
358 using value_type = T;
363 using const_reference = value_type
const&;
365 using token_type = notifier_type::token_type;
366 using awaiter_type = notifier_type::awaiter_type;
370 _pimpl->remove_owner(*
this);
379 _pimpl->add_owner(*
this);
390 _pimpl->add_owner(*
this);
405 if (
this == &other or _pimpl == other._pimpl) {
410 _pimpl->reseat_owners(other._pimpl);
414 token_type subscribe(std::invocable<value_type>
auto&& callback)
noexcept
416 return _notifier.subscribe(
hi_forward(callback));
419 awaiter_type
operator co_await()
const noexcept
421 return _notifier.operator
co_await();
435 return _pimpl->const_proxy();
449 return _pimpl->const_proxy();
465 return _pimpl->proxy();
474 return *const_proxy();
485 return const_proxy();
492 observable(std::convertible_to<value_type>
auto&& value) noexcept : _pimpl(std::make_shared<impl_type>(
hi_forward(value)))
494 _pimpl->add_owner(*
this);
516 auto operator++() noexcept requires(requires(value_type a) { {++a}; })
528 auto operator--() noexcept requires(requires(value_type a) { {--a}; })
540 auto operator++(
int)
noexcept requires(
requires(value_type a) { {a++}; })
552 auto operator--(
int)
noexcept requires(
requires(value_type a) { {a--}; })
564 auto operator+=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a +=
hi_forward(b)}; })
576 auto operator-=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a -=
hi_forward(b)}; })
588 auto operator*=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a *=
hi_forward(b)}; })
600 auto operator/=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a /=
hi_forward(b)}; })
612 auto operator%=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a %=
hi_forward(b)}; })
624 auto operator&=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a &=
hi_forward(b)}; })
636 auto operator|=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a |=
hi_forward(b)}; })
648 auto operator^=(
auto&& rhs)
noexcept requires(
requires(value_type a,
decltype(rhs) b) { {a ^=
hi_forward(b)}; })
678 notifier_type _notifier;
693 using type =
typename observable<T>::value_type;
697using 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:588
auto operator--(int) noexcept
Post decrement.
Definition observable.hpp:552
observable() noexcept
Construct an observable.
Definition observable.hpp:377
observable & operator=(observable const &other) noexcept
Chain with another observable.
Definition observable.hpp:403
auto operator>>=(auto &&rhs) noexcept
Inplace shift right.
Definition observable.hpp:672
auto operator--() noexcept
Pre decrement.
Definition observable.hpp:528
observable(std::convertible_to< value_type > auto &&value) noexcept
Construct an observable with its value set.
Definition observable.hpp:492
auto operator/=(auto &&rhs) noexcept
Inplace divide.
Definition observable.hpp:600
auto operator|=(auto &&rhs) noexcept
Inplace bitwise or.
Definition observable.hpp:636
proxy_type proxy() noexcept
proxy a writable reference to the shared-value.
Definition observable.hpp:462
auto operator++() noexcept
Pre increment.
Definition observable.hpp:516
auto operator&=(auto &&rhs) noexcept
Inplace bitwise and.
Definition observable.hpp:624
const_reference operator*() const noexcept
Dereference to the value.
Definition observable.hpp:472
auto operator%=(auto &&rhs) noexcept
Inplace remainder.
Definition observable.hpp:612
observable(observable const &other) noexcept
Construct an observable and chain it to another.
Definition observable.hpp:388
auto operator+=(auto &&rhs) noexcept
Inplace add.
Definition observable.hpp:564
const_proxy_type operator->() const noexcept
Member select.
Definition observable.hpp:483
auto operator^=(auto &&rhs) noexcept
Inplace bitwise xor.
Definition observable.hpp:648
const_proxy_type const_proxy() const noexcept
proxy a constant reference to the shared value.
Definition observable.hpp:432
auto operator-=(auto &&rhs) noexcept
Inplace subtract.
Definition observable.hpp:576
auto operator<<=(auto &&rhs) noexcept
Inplace shift left.
Definition observable.hpp:660
observable & operator=(std::convertible_to< value_type > auto &&value) noexcept
Assign a new value.
Definition observable.hpp:502
auto operator++(int) noexcept
Post increment.
Definition observable.hpp:540
proxy_type proxy() const noexcept
proxy a constant reference to the shared value.
Definition observable.hpp:446
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:687
Definition concepts.hpp:38