51 using clock = std::chrono::steady_clock;
61 decltype(queue_) retired;
63 std::scoped_lock lk(m_);
65 std::swap(queue_, retired);
84 void schedule(std::function<
void()> fn)
override {
post(std::move(fn)); }
86 std::function<
void()> fn)
override {
92 void post(std::function<
void()> fn)
override {
100 std::lock_guard lk(m_);
101 if (closed_) {
return; }
102 queue_.push(Entry{add_delay(now_, delay), ++seq_, std::move(fn)});
107 std::lock_guard lk(m_);
112 [[nodiscard]] std::size_t
pending() const noexcept {
113 std::lock_guard lk(m_);
114 return queue_.size();
120 if (delta < duration::zero()) {
121 throw std::invalid_argument(
"VirtualTimeExecutor cannot move time backwards");
128 if (target <
now()) {
129 throw std::invalid_argument(
"VirtualTimeExecutor cannot move time backwards");
131 std::size_t fired = 0;
133 std::function<void()> fn;
135 std::lock_guard lk(m_);
136 if (queue_.empty() || queue_.top().deadline > target) {
138 if (target > now_) { now_ = target; }
141 const auto deadline = queue_.top().deadline;
142 fn = std::move(queue_.top().fn);
144 if (deadline > now_) { now_ = deadline; }
151 std::string_view{
"executor.virtual_time.advance"},
152 std::current_exception());
163 std::size_t fired = 0;
165 std::function<void()> fn;
167 std::lock_guard lk(m_);
168 if (queue_.empty())
break;
169 const auto deadline = queue_.top().deadline;
170 fn = std::move(queue_.top().fn);
172 if (deadline > now_) { now_ = deadline; }
178 std::string_view{
"executor.virtual_time.run_until_idle"},
179 std::current_exception());
188 std::priority_queue<Entry, std::vector<Entry>, Cmp> retired;
190 std::lock_guard lk(m_);
191 std::swap(queue_, retired);
198 if (delay <= duration::zero()) {
return now; }
199 return now > duration::max() - delay ? duration::max() :
now + delay;
205 mutable std::function<void()> fn;
208 bool operator()(
const Entry& a,
const Entry& b)
const noexcept {
209 if (a.deadline != b.deadline)
return a.deadline > b.deadline;
210 return a.seq > b.seq;
214 mutable std::mutex m_;
216 std::uint64_t seq_{0};
217 std::priority_queue<Entry, std::vector<Entry>, Cmp> queue_;
218 bool closed_ =
false;
229 bool await_ready()
const noexcept {
return false; }
230 void await_suspend(std::coroutine_handle<> h)
const {
231 vt.
post_after(delay, [h]()
mutable { h.resume(); });
233 void await_resume()
const noexcept {}
235 return Awaiter{vt, delay};
Tiny interface — anything that can post a function to run after a delay.
Definition property_ops.hpp:62
Abstract executor interface — schedules a callable to run "somewhere".
Definition executor.hpp:37
Definition virtual_time_executor.hpp:49
aria::SchedulerCaps caps() const noexcept override
Capabilities: Post (immediate), Delay (deadline-keyed), GraphSafe.
Definition virtual_time_executor.hpp:77
duration now() const noexcept
Current virtual time (since construction).
Definition virtual_time_executor.hpp:106
VirtualTimeExecutor()=default
~VirtualTimeExecutor() override
Definition virtual_time_executor.hpp:60
std::chrono::milliseconds duration
Definition virtual_time_executor.hpp:52
std::size_t advance_to(duration target)
Advance to an absolute virtual time target (must be >= now()).
Definition virtual_time_executor.hpp:127
VirtualTimeExecutor & operator=(VirtualTimeExecutor &&)=delete
void post_after(duration delay, std::function< void()> fn) override
Schedule to run after delay of virtual time.
Definition virtual_time_executor.hpp:98
void schedule_after(std::chrono::milliseconds delay, std::function< void()> fn) override
Submit fn for execution after delay.
Definition virtual_time_executor.hpp:85
std::size_t advance_by(duration delta)
Advance virtual time by delta, firing tasks in deadline order.
Definition virtual_time_executor.hpp:119
std::size_t pending() const noexcept
Number of scheduled tasks not yet fired.
Definition virtual_time_executor.hpp:112
std::chrono::steady_clock clock
Definition virtual_time_executor.hpp:51
void clear() noexcept
Drop all scheduled tasks without firing them.
Definition virtual_time_executor.hpp:187
void post(std::function< void()> fn) override
IExecutor: schedule "now" — runs at the current virtual time when the next advance_by()/run_until_idl...
Definition virtual_time_executor.hpp:92
VirtualTimeExecutor(const VirtualTimeExecutor &)=delete
VirtualTimeExecutor & operator=(const VirtualTimeExecutor &)=delete
std::size_t run_until_idle()
Run everything currently queued without advancing time beyond the last deadline.
Definition virtual_time_executor.hpp:162
void schedule(std::function< void()> fn) override
Submit fn for execution "soon". Defines Caps::Post.
Definition virtual_time_executor.hpp:84
VirtualTimeExecutor(VirtualTimeExecutor &&)=delete
Definition async_command.hpp:118
auto schedule_after(VirtualTimeExecutor &vt, VirtualTimeExecutor::duration delay)
Awaiter that resumes the coroutine after delay of virtual time.
Definition virtual_time_executor.hpp:224
void report_callback_failure(std::string_view category, std::exception_ptr exception, std::string_view message={}) noexcept
Report a callback failure.
SchedulerCaps
Definition scheduler.hpp:83
@ Post
Can submit "fire now" work.
Definition scheduler.hpp:89
@ GraphSafe
Safe to use as the graph-thread executor — i.e.
Definition scheduler.hpp:107
@ Pumpable
Posted work is held in a queue until a pump-style call drains it (e.g.
Definition scheduler.hpp:102
@ Delay
Can submit work after a wall-clock or virtual-time delay.
Definition scheduler.hpp:93
@ WorkerSafe
Safe to host blocking worker tasks (e.g.
Definition scheduler.hpp:111