///|
/// How long `run` waits after a requested shutdown for handlers that are
/// still running before it cancels them.
pub const DEFAULT_SHUTDOWN_GRACE_MS : Int32 = 10000
///|
/// Counts the handlers that have started and not yet ended (event middleware
/// runs, event handlers, and interaction tasks), so a shutdown can wait for
/// them within its grace period.
priv struct HandlerTracker {
mut active : Int32
idle : @cond_var.Cond
}
///|
fn HandlerTracker::new() -> HandlerTracker {
{ active: 0, idle: @cond_var.Cond(), }
}
///|
fn HandlerTracker::enter(self : HandlerTracker) -> Unit {
self.active += 1
}
///|
fn HandlerTracker::leave(self : HandlerTracker) -> Unit {
self.active -= 1
if self.active == 0 {
self.idle.broadcast()
}
}
///|
async fn HandlerTracker::wait_idle(self : HandlerTracker) -> Unit {
while self.active > 0 {
self.idle.wait()
}
}
///|
/// Run `body`, tracked while it runs.
async fn HandlerTracker::track(
self : HandlerTracker,
body : async () -> Unit,
) -> Unit {
self.enter()
defer self.leave()
body()
}
///|
/// Wrap `spawner` so every task it starts is tracked while its body runs. A
/// task that never starts its body, as `App::spawner` does once its intake has
/// closed, is never tracked.
fn HandlerTracker::spawner(
self : HandlerTracker,
spawner : @app.Spawner,
) -> @app.Spawner {
body => spawner(() => self.track(body))
}