55#include <unordered_set>
65 using std::runtime_error::runtime_error;
105 using Buffer = std::vector<detail::NodeHandle>;
109 reads_.swap(reusable);
114 reads_.swap(*reusable_);
124 for (
const auto& n : reads_) {
125 if (n.get() == &src)
return;
127 reads_.emplace_back(&src);
130 [[nodiscard]]
const std::vector<detail::NodeHandle>&
reads() const noexcept {
return reads_; }
131 void clear() noexcept { reads_.clear(); }
135 Buffer* reusable_ =
nullptr;
158 if (owner_thread_ == std::thread::id{}) {
159 const_cast<Graph*
>(
this)->owner_thread_ = std::this_thread::get_id();
162 assert(owner_thread_ == std::this_thread::get_id()
163 &&
"reactive::Graph accessed from a non-UI thread. "
164 "Use Dispatcher::post to marshal updates back to the graph thread.");
182 assert(batch_depth_ > 0 &&
"end_batch without matching begin_batch");
183 if (--batch_depth_ == 0 && !flushing_) {
188 [[nodiscard]]
bool in_batch() const noexcept {
return batch_depth_ > 0; }
204 if (n.queued_)
return;
205 pending_.emplace_back(&n);
228 return tracker_stack_.empty() ? nullptr : tracker_stack_.back();
234 assert(!tracker_stack_.empty() && tracker_stack_.back() == ctx);
236 tracker_stack_.pop_back();
244 assert(!tracker_stack_.empty() && tracker_stack_.back() ==
nullptr);
245 tracker_stack_.pop_back();
254 bool pull_settle_(
Node& n);
264 std::vector<Node*> color_stack_;
265 bool color_in_use_ =
false;
269 bool flushing_ =
false;
271 int batch_depth_ = 0;
275 std::vector<detail::NodeHandle> pending_;
276 std::vector<detail::NodeHandle> round_;
282 std::vector<detail::NodeHandle> pulling_stack_;
285 std::vector<TrackingContext*> tracker_stack_;
287 std::thread::id owner_thread_{};
291 static constexpr int kMaxFlushRounds = 100;
331 if constexpr (std::is_void_v<
decltype(fn())>) {
332 std::forward<Fn>(fn)();
334 return std::forward<Fn>(fn)();
359 std::string_view{
"reactive.batch_scope.end_batch"},
360 std::current_exception());
369auto batch(Fn&& fn) ->
decltype(fn()) {
371 if constexpr (std::is_void_v<
decltype(fn())>) {
372 std::forward<Fn>(fn)();
374 return std::forward<Fn>(fn)();
BatchScope()
Definition graph.hpp:348
RAII batch guard: { BatchScope b; ...; } or use batch([&]{...}).
Definition graph.hpp:346
BatchScope(const BatchScope &)=delete
BatchScope & operator=(const BatchScope &)=delete
BatchScope()
Definition graph.hpp:348
~BatchScope() noexcept
Definition graph.hpp:349
Thrown when flush detects a dependency cycle.
Definition graph.hpp:63
TrackingContext * current_tracker() noexcept
Definition graph.hpp:227
void on_source_changed(Node &src)
Called after a Source has committed a new value: bumps its version and colors the downstream MaybeDir...
Definition graph.inl:175
void enqueue_dirty(Node &n)
Enqueue a node into the current flush round's "pending" set.
Definition graph.hpp:203
void pop_tracker(TrackingContext *ctx)
Definition graph.hpp:233
friend class Node
Definition graph.hpp:145
bool in_batch() const noexcept
Definition graph.hpp:188
void push_tracker(TrackingContext *ctx)
Push / pop a tracker (used by RAII TrackerScope).
Definition graph.hpp:232
void begin_batch() noexcept
Open a new batch. Nesting is legal; the outermost close flushes.
Definition graph.hpp:173
void enter_untracked()
Enter / leave an untracked scope.
Definition graph.hpp:242
bool pull(Node &n)
Force-evaluate a single node if it is Dirty / MaybeDirty.
Definition graph.inl:342
void end_batch()
Close the current batch; triggers a flush once the outermost batch closes (unless we are already insi...
Definition graph.hpp:180
void leave_untracked()
Definition graph.hpp:243
void assert_on_graph_thread() const noexcept
Definition graph.hpp:155
void flush()
Evaluate every dirty node in topological order.
Definition graph.inl:194
Common base for every node participating in the reactive graph.
Definition node.hpp:136
static Graph & graph() noexcept
Returns the process-wide singleton Graph this node belongs to.
Definition graph.inl:30
~TrackerScope()
Definition graph.hpp:310
TrackerScope & operator=(const TrackerScope &)=delete
TrackerScope(TrackingContext &ctx)
Definition graph.hpp:307
TrackerScope(const TrackerScope &)=delete
Per-recompute tracking context for a single Derivation evaluation.
Definition graph.hpp:103
std::vector< detail::NodeHandle > Buffer
Definition graph.hpp:105
void clear() noexcept
Definition graph.hpp:131
~TrackingContext()
Definition graph.hpp:111
TrackingContext(Buffer &reusable) noexcept
Definition graph.hpp:108
TrackingContext & operator=(const TrackingContext &)=delete
TrackingContext()=default
void record_read(Node &src)
Records one upstream read.
Definition graph.hpp:122
TrackingContext(const TrackingContext &)=delete
const std::vector< detail::NodeHandle > & reads() const noexcept
Definition graph.hpp:130
RAII: within the scope, every dep() behaves like a plain get().
Definition graph.hpp:318
UntrackedScope & operator=(const UntrackedScope &)=delete
~UntrackedScope()
Definition graph.hpp:321
UntrackedScope()
Definition graph.hpp:320
UntrackedScope(const UntrackedScope &)=delete
#define ARIA_ABI_API
Definition export.hpp:21
Definition computed.hpp:60
auto batch(Fn &&fn) -> decltype(fn())
Sugar: batch([&]{ firstName = "..."; lastName = "..."; }).
Definition graph.hpp:369
auto untracked(Fn &&fn) -> decltype(fn())
Sugar: untracked([&]{ ... }).
Definition graph.hpp:329
std::function< void(int phase, const Node *node, int round, bool changed)> FlushTraceFn
Definition graph.hpp:84
std::shared_ptr< FlushTraceFn > & flush_trace_hook_() noexcept
TrackingContext * current_tracker() noexcept
Returns the current tracker of the global graph.
Definition graph.hpp:300
void report_callback_failure(std::string_view category, std::exception_ptr exception, std::string_view message={}) noexcept
Report a callback failure.
One "upstream read" record.
Definition graph.hpp:98
Node * source
The upstream node that was read.
Definition graph.hpp:99