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.

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 for the handler contract and a worked frame handler.

Module contents

Types

TypeKindDescription
HandlerrecordWhat a host installs to answer suspensions.
InstalledrecordAn installed handler, and the obligation to put back what it displaced.
WaitingrecordWhat a park exposes to the handler driving it.

Types#

Handlerrecord#

record Handler ...

What a host installs to answer suspensions.

Members

NameKindDescription
parkmethodParks or drives this Waiting; cleanup cancels the subscription.
canParkmethodReports whether this handler can park the current execution.
shutdownmethodReleases scheduling state owned by this handler.

parkmethod#

park: function(self: Handler, waiting: Waiting, cleanup: function(): nil): nil

Parks or drives this Waiting; cleanup cancels the subscription.

Arguments
NameTypeDescription
selfHandler
waitingWaiting
cleanupfunction(): nil
Returns
TypeDescription
nil

canParkmethod#

canPark: function(self: Handler): boolean

Reports whether this handler can park the current execution.

Arguments
NameTypeDescription
selfHandler
Returns
TypeDescription
boolean

shutdownmethod#

shutdown: function(self: Handler): nil

Releases scheduling state owned by this handler.

Arguments
NameTypeDescription
selfHandler
Returns
TypeDescription
nil

Installedrecord#

record Installed is nupp.Closeable ...

An installed handler, and the obligation to put back what it displaced.

Members

NameKindDescription
closemethodRestores the outer handler and settles every park this installation accepted, without suspending.
handlerfieldHandler supplied by the caller.

closemethod#

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
NameTypeDescription
takes selfInstalled
Returns
TypeDescription
nil

handlerfield#

handler: Handler

Handler supplied by the caller.

Waitingrecord#

record Waiting ...

What a park exposes to the handler driving it.

Members

NameKindDescription
readymethodReports whether the subscription has settled.
onResumemethodRegisters a wake callback for the waiting scheduler.
operationfieldDiagnostic operation name supplied to suspend.

readymethod#

ready: function(self: Waiting): boolean

Reports whether the subscription has settled.

Arguments
NameTypeDescription
selfWaiting
Returns
TypeDescription
boolean

onResumemethod#

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
NameTypeDescription
selfWaiting
wakefunction(): nil
Returns
TypeDescription
nil

operationfield#

operation: string

Diagnostic operation name supplied to suspend.