# `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.