nupp.suspension
Waiting without blocking the thread.
A suspension-aware call parks the frame it is in rather than stopping the process, and whoever installed a handler decides what runs meanwhile -- an event loop, a poll, the next frame.
local suspension = require("nupp.suspension")
local function readLine(reader: Reader): string
return suspension.suspend("example.readLine", function(
resume: function(string),
context: suspension.Context
): function()
const subscription = reader:onLine(resume)
return function(): nil
subscription:release()
end
end)
endsuspend parks on something that will be ready later, source registers the pump that makes it ready, and poll drives every registered pump once. handled says whether a handler is listening; without one a park drives those pumps on this thread and blocks after all. canSuspend returns whether a park would be permitted here at all, and create makes a coroutine that inherits the handler.
Installing a handler, and driving the parks it accepts, is the other side of this: nupp.suspension.host. A library needs none of it.
This is the layer underneath. Somewhere to put children discovered over time, with one answer for failure and cancellation, is nupp.tasks; real parallelism is nupp.workers. Come here directly to make a library waitable, or to write a combinator neither of those has.
An arbitrary blocking Lua or C call still blocks the thread. A library opts in by parking through this module; nothing intercepts calls that do not.
See Suspension.
Submodules
| Module | Description |
|---|---|
nupp.suspension.cancellation | Canonical task-cancellation identity within one Lua state. |
nupp.suspension.host | Deciding what runs while something waits. |
nupp.suspension.spi | Shared interfaces for scheduler integration. |
Module contents
Types
| Type | Kind | Description |
|---|---|---|
Context | record | What a library is handed while it subscribes. |
Source | record | A readiness pump, and the handle that owns its lifetime. |
Types#
Contextrecord#
record Context ...What a library is handed while it subscribes.
Members
| Name | Kind | Description |
|---|---|---|
source | method | Registers a source associated with this subscription, as nupp.suspension.spi.Provider.source registers one outside any. |
uses | method | Associates an existing source with this wait without changing its identity. |
sourcemethod#
source: function(
self: Context,
name: string,
order: integer,
poll: function(): integer,
wait: (function(integer): integer)?,
active: (function(source: Source): boolean)?
): SourceRegisters a source associated with this subscription, as nupp.suspension.spi.Provider.source registers one outside any.
Arguments
| Name | Type | Description |
|---|---|---|
self | Context | |
name | string | |
order | integer | |
poll | function(): integer | |
wait | (function(integer): integer)? | |
active | (function(source: Source): boolean)? |
Returns
| Type | Description |
|---|---|
Source |
Sourcerecord#
record Source ...A readiness pump, and the handle that owns its lifetime.
Members
| Name | Kind | Description |
|---|---|---|
release | method | Unregisters this source without suspending; repeated calls are harmless. |
name | field | Diagnostic identity of the readiness source. |
order | field | Where in a poll pass this source runs; smaller orders are polled first. |
wait | field | Optional bounded blocking waiter receiving milliseconds and returning progress. |
active | field | Optional predicate deciding whether the source has outstanding work. |
releasemethod#
Unregisters this source without suspending; repeated calls are harmless. The provider supplies it with the registration.
Arguments
| Name | Type | Description |
|---|---|---|
self | Source |
Returns
| Type | Description |
|---|---|
nil |
waitfield#
wait: (function(integer): integer)?Optional bounded blocking waiter receiving milliseconds and returning progress.