try_tick() method for st swactor runtimes

This commit is contained in:
Zachery Aaron Shores-Chmielewski 2026-07-15 14:48:13 +04:00
parent e8a44c3666
commit 17491c5247
2 changed files with 44 additions and 17 deletions

View file

@ -438,18 +438,42 @@ impl Runtime {
}
}
/// Return whether the single-threaded runtime currently has schedulable work.
///
/// Panics if called on a multi-threaded runtime — use `run()` instead.
pub fn has_work(&self) -> bool {
assert!(
self.config.num_threads < 2,
"has_work() is only valid for single-threaded runtimes; use run() for multi-threaded"
);
self.tick_workers.borrow().iter().any(Worker::has_work)
}
/// Try to drive one tick of the single-threaded runtime.
///
/// Returns `false` if no worker performed work.
/// Returns `true` if at least one worker performed work.
///
/// Panics if called on a multi-threaded runtime — use `run()` instead.
pub fn try_tick(&self) -> bool {
assert!(
self.config.num_threads < 2,
"try_tick() is only valid for single-threaded runtimes; use run() for multi-threaded"
);
let tc = self.make_tick_context();
self.tick_workers
.borrow_mut()
.iter_mut()
.fold(false, |did_work, worker| worker.tick_once(&tc) || did_work)
}
/// Drive one tick of the single-threaded worker.
///
/// Panics if called on a multi-threaded runtime — use `run()` instead.
pub fn tick(&self) {
assert!(
self.config.num_threads < 2,
"tick() is only valid for single-threaded runtimes; use run() for multi-threaded"
);
let tc = self.make_tick_context();
for worker in self.tick_workers.borrow_mut().iter_mut() {
worker.tick_once(&tc);
}
let _ = self.try_tick();
}
/// Spawn worker threads and start processing, returning a handle

View file

@ -105,6 +105,17 @@ impl Worker {
}
}
pub(crate) fn has_work(&self) -> bool {
self.has_backlog
|| !self.spawn_rx.is_empty()
|| !self.transfer_rx.is_empty()
|| !self.admin_rx.is_empty()
|| self
.worker_ext
.as_ref()
.map_or(false, |e| e.has_pending_work())
}
/// Run one iteration of the worker loop. Returns `true` if any work was done.
/// Drain the spawn queue, inserting new actors into the pool.
/// Used in phases 1 and 4 of tick_once.
@ -283,15 +294,7 @@ impl Worker {
// Fast idle path: skip the entire tick when nothing could have changed.
// Cost: ~3 atomic loads, zero syscalls, zero actor iteration.
if !self.has_backlog
&& self.spawn_rx.is_empty()
&& self.transfer_rx.is_empty()
&& self.admin_rx.is_empty()
&& !self
.worker_ext
.as_ref()
.map_or(false, |e| e.has_pending_work())
{
if !self.has_work() {
return false;
}