# `nupp.suspension.host` Deciding what runs while something waits. `nupp.suspension` is what a library parks through. This is the other side: what a host installs to answer those parks, and what a scheduler needs to drive them. The two are separate because the two jobs are. A library never installs a handler, and a host never subscribes to a readiness source, so neither has to read past the other's operations to find its own. ```nupp:fragment local host = require("nupp.suspension.host") local function application(): nil with installation = host.install(frameHandler) do work() end end ``` `install` puts a handler on the current coroutine for the extent of the `with`. Driving the readiness pumps while it waits is `nupp.suspension`'s `poll`: the pumps are registered through that module and drained through it, by a scheduler here or by an embedding host that never installs a handler at all. `create` makes a coroutine that inherits the handler, so work started inside a handled extent is handled too. A *driver* stands in front of a host rather than being one: a task scope opened in a frame installs one so the frame's own waits keep its children running. `installDriver` says so, `delegatedPark` and `delegatedCanPark` capture the handler it displaces so what it cannot satisfy goes outward, `derive` builds the wait to hand there, and the turn budget bounds how long it may run before it owes its host a turn. See [Suspension](../../../../learn/runtime/concurrency/suspension/index.html) for the handler contract and a worked frame handler. ## Types ### `Handler` _record_ ```nupp record Handler ... ``` What a host installs to answer suspensions. #### Members | Name | Kind | Description | | --- | --- | --- | | [`park`](#nupp.suspension.host.Handler.park) | method | Parks or drives this Waiting; cleanup cancels the subscription. | | [`canPark`](#nupp.suspension.host.Handler.canPark) | method | Reports whether this handler can park the current execution. | | [`shutdown`](#nupp.suspension.host.Handler.shutdown) | method | Releases scheduling state owned by this handler. | #### `park` _method_ ```nupp park: function(self: Handler, waiting: Waiting, cleanup: function(): nil): nil ``` Parks or drives this Waiting; `cleanup` cancels the subscription. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Handler` | | | `waiting` | `Waiting` | | | `cleanup` | `function(): nil` | | ##### Returns | Type | Description | | --- | --- | | `nil` | | #### `canPark` _method_ ```nupp canPark: function(self: Handler): boolean ``` Reports whether this handler can park the current execution. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Handler` | | ##### Returns | Type | Description | | --- | --- | | `boolean` | | #### `shutdown` _method_ ```nupp shutdown: function(self: Handler): nil ``` Releases scheduling state owned by this handler. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Handler` | | ##### Returns | Type | Description | | --- | --- | | `nil` | | ### `Installed` _record_ ```nupp record Installed is nupp.Closeable ... ``` An installed handler, and the obligation to put back what it displaced. #### Members | Name | Kind | Description | | --- | --- | --- | | [`close`](#nupp.suspension.host.Installed.close) | method | Restores the outer handler and settles every park this installation accepted, without suspending. | | [`handler`](#nupp.suspension.host.Installed.handler) | field | Handler supplied by the caller. | #### `close` _method_ ```nupp close: @nosuspend function(takes self: Installed): nil ``` Restores the outer handler and settles every park this installation accepted, without suspending. The provider supplies it with the installation; a drain that fails leaves the installation to be closed again. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `takes self` | `Installed` | | ##### Returns | Type | Description | | --- | --- | | `nil` | | #### `handler` _field_ ```nupp handler: Handler ``` Handler supplied by the caller. ### `Waiting` _record_ ```nupp record Waiting ... ``` What a park exposes to the handler driving it. #### Members | Name | Kind | Description | | --- | --- | --- | | [`ready`](#nupp.suspension.host.Waiting.ready) | method | Reports whether the subscription has settled. | | [`onResume`](#nupp.suspension.host.Waiting.onResume) | method | Registers a wake callback for the waiting scheduler. | | [`operation`](#nupp.suspension.host.Waiting.operation) | field | Diagnostic operation name supplied to suspend. | #### `ready` _method_ ```nupp ready: function(self: Waiting): boolean ``` Reports whether the subscription has settled. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Waiting` | | ##### Returns | Type | Description | | --- | --- | | `boolean` | | #### `onResume` _method_ ```nupp onResume: function(self: Waiting, wake: function(): nil): nil ``` Registers a wake callback for the waiting scheduler. Settle-safe: where the wait has already settled, `wake` is called before this returns rather than stored. A handler may therefore arm once and then yield until `ready` returns true, without a recheck loop around the arming. ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Waiting` | | | `wake` | `function(): nil` | | ##### Returns | Type | Description | | --- | --- | | `nil` | | #### `operation` _field_ ```nupp operation: string ``` Diagnostic operation name supplied to suspend.