56class AutoReactionNode final :
public Node,
public std::enable_shared_from_this<AutoReactionNode> {
58 explicit AutoReactionNode(std::function<
void()> fn)
65 ~AutoReactionNode()
override {
73 [[nodiscard]] std::shared_ptr<Node> retain_for_recompute() noexcept
override {
74 return weak_from_this().lock();
89 bool recompute()
override {
90 TrackingContext ctx{read_buffer_};
92 TrackerScope guard(ctx);
97 const auto& reads = ctx.reads();
100 while (edge_pool_.size() < reads.size()) edge_pool_.emplace_back();
104 for (
const auto& read : reads) {
114 std::function<void()> fn_;
116 std::deque<Edge> edge_pool_;
117 std::size_t active_edges_ = 0;
131 template<std::invocable<> Fn>
133 : node_(
std::make_shared<detail::AutoReactionNode>(
std::move(fn))) {}
141 void stop() noexcept { node_.reset(); }
143 [[nodiscard]]
bool active() const noexcept {
return static_cast<bool>(node_); }
149 return ::aria::Subscription{std::move(node_)};
153 std::shared_ptr<detail::AutoReactionNode> node_;
159template<PropertyValue T>
167 auto primed = std::make_shared<bool>(
false);
168 auto reaction = std::make_shared<detail::AutoReactionNode>(
169 [
this, fn = std::move(fn), primed] {
170 const auto& v = this->
get();
171 if (!*primed) { *primed =
true;
return; }
174 reaction->set_debug_name(
"Computed::on_changed");
175 return ::aria::Subscription{std::move(reaction)};
178template<PropertyValue T>
183 auto reaction = std::make_shared<detail::AutoReactionNode>(
184 [
this, fn = std::move(fn)] { fn(this->
get()); });
185 reaction->set_debug_name(
"Computed::bind");
186 return ::aria::Subscription{std::move(reaction)};
189template<PropertyValue T>
191 auto last = std::make_shared<T>(
peek());
192 auto reaction = std::make_shared<detail::AutoReactionNode>(
193 [
this, fn = std::move(fn), last] {
194 T new_val = this->
get();
195 T old = std::move(*last);
199 if (!(old == new_val)) fn(old, new_val);
201 reaction->set_debug_name(
"Computed::observe");
202 return ::aria::Subscription{std::move(reaction)};
Effect(Fn fn)
Runs fn once eagerly (to collect its initial dependency set), then automatically re-runs it whenever ...
Definition effect.hpp:132
RAII handle to a single subscription.
Definition subscription.hpp:44
T peek() const noexcept(std::is_nothrow_copy_constructible_v< T >)
Non-tracking snapshot read.
Definition computed.hpp:166
::aria::Subscription on_changed(std::function< void(const T &)> fn)
Definition effect.hpp:160
T get() const
Return the cached value, ensuring it is up to date.
Definition computed.hpp:135
::aria::Subscription observe(std::function< void(const T &, const T &)> fn)
Definition effect.hpp:190
::aria::Subscription bind(std::function< void(const T &)> fn)
Definition effect.hpp:179
Effect(Effect &&) noexcept=default
Effect(const Effect &)=delete
::aria::Subscription into_subscription() &&noexcept
Transfer ownership into a unified aria::Subscription, so that an Effect can be dropped into any Subsc...
Definition effect.hpp:148
void stop() noexcept
Explicitly cancel (without waiting for destruction).
Definition effect.hpp:141
Effect(Fn fn)
Runs fn once eagerly (to collect its initial dependency set), then automatically re-runs it whenever ...
Definition effect.hpp:132
Effect & operator=(const Effect &)=delete
bool active() const noexcept
Definition effect.hpp:143
void set_depth(std::uint32_t d) noexcept
Definition node.hpp:209
Node(NodeKind kind) noexcept
Definition node.hpp:144
void retire_() noexcept
Retire before derived members (including user captures) are destroyed.
Definition graph.inl:42
void attach_as_observer_of(Node &source, Edge &edge) noexcept
Definition graph.inl:64
void clear_sources() noexcept
Drop every upstream edge.
Definition graph.inl:107
std::vector< detail::NodeHandle > Buffer
Definition graph.hpp:105
Definition computed.hpp:60
NodeKind
Definition node.hpp:87
@ Reaction
Definition node.hpp:90
Definition validation_key.hpp:110