@eryx/thread Module

Run Luau work in isolated child runtimes backed by OS threads.

Threads can be spawned one at a time with thread.spawn, reused through a ThreadPool, or preconfigured as a ThreadWorker for repeated jobs.

Child entrypoints always receive a context object. That context exposes:

Example:

local thread = require("@eryx/thread")

local handle = thread.spawn(function(ctx)
	ctx:send("ready")
	local input = ctx:recv()
	return input * 2
end)

print(handle:recv()) -- "ready"
handle:send(21)
print(handle:join()) -- 42

Summary

Classes

value: InitialData
ThreadContext:send(value: SendData)()
ThreadContext:update(value: UpdateData)()
ThreadContext:recv()RecvData
status: Status
error: Exception?
onError: (((handle: ThreadHandle<SendData, RecvData, ResultData>, err: Exception) → ()))?
ThreadHandle:send(value: SendData)()
ThreadHandle:recv()RecvData
ThreadHandle:join()ResultData
status: FutureStatus
error: Exception?
update: UpdateData?
onError: (((future: Future<UpdateData, ResultData>, err: Exception) → ()))?
onUpdate: (((future: Future<UpdateData, ResultData>, value: UpdateData) → ()))?
Future:wait()ResultData
workers: number
active: number
queued: number
onError: (((future: Future<T, U>, err: Exception) → ()))?
onUpdate: (((future: Future<T, U>, value: T) → ()))?
ThreadPool:spawn<InitialData, SendData, UpdateData, RecvData, ResultData>(entry: string | ThreadEntryFunction<InitialData, SendData, UpdateData, RecvData, ResultData>, context: InitialData)Future<UpdateData, ResultData>
workers: number
active: number
queued: number
onError: (((future: Future<UpdateData, ResultData>, err: Exception) → ()))?
onUpdate: (((future: Future<UpdateData, ResultData>, value: UpdateData) → ()))?
ThreadWorker:submit()Future<UpdateData, ResultData>

Functions

thread.spawn<InitialData, SendData, UpdateData, RecvData, ResultData>(entry: string | ThreadEntryFunction<InitialData, SendData, UpdateData, RecvData, ResultData>, context: InitialData)ThreadHandle<SendData, RecvData, ResultData>
thread.worker<InitialData, SendData, UpdateData, RecvData, ResultData>(options: WorkerOptions<InitialData, SendData, UpdateData, RecvData, ResultData>)ThreadWorker<InitialData, UpdateData, ResultData>

API Reference

Classes

ThreadContext<InitialData, SendData, UpdateData, RecvData>

Context object passed into a child thread entrypoint.

Generic parameters are expressed from the child's point of view:

  • InitialData: initial payload supplied by the parent
  • SendData: values sent from the child to the parent via send
  • UpdateData: values published from the child to the parent via update
  • RecvData: values received from the parent via recv

Properties

value: InitialData

Initial payload provided when the thread or job was started.

ThreadContext:send

Send a message from the child thread back to the parent handle.

ThreadContext:send(value: SendData)()

Parameters

value: SendData

Message payload delivered to the parent through handle:recv().

ThreadContext:update

Publish a progress update for a pooled or worker-backed job.

Updates are surfaced on the parent-side future through future.update and future.onUpdate.

ThreadContext:update(value: UpdateData)()

Parameters

value: UpdateData

Progress payload to publish to the parent runtime.

ThreadContext:recv

⚠ Yields

Wait for the next message from the parent.

ThreadContext:recv()RecvData

Returns

RecvData

Next payload sent from the parent thread or pooled caller.

ThreadHandle<SendData, RecvData, ResultData>

Handle to a directly spawned child thread.

Generic parameters are expressed from the parent's point of view:

  • SendData: values the parent sends to the child
  • RecvData: values the parent receives from the child
  • ResultData: final value returned by join

Properties

status: Status

Current lifecycle state of the child thread.

error: Exception?

Copied exception payload when the thread has failed, otherwise nil.

onError: (((handle: ThreadHandle<SendData, RecvData, ResultData>, err: Exception) → ()))?

Optional callback invoked on the parent runtime when the thread errors.

ThreadHandle:send

Send a value from the parent to the child thread.

ThreadHandle:send(value: SendData)()

Parameters

value: SendData

Payload made available to the child through context:recv().

ThreadHandle:recv

⚠ Yields

Wait for the next message sent from the child thread.

ThreadHandle:recv()RecvData

Returns

RecvData

Next payload published by the child through context:send().

ThreadHandle:join

⚠ Yields

Wait for the thread to finish and return its final result.

ThreadHandle:join()ResultData

Returns

ResultData

Final value returned by the child entrypoint.

ThreadHandle:kill

Request that the child thread stop as soon as possible.

ThreadHandle:kill()()

Future<UpdateData, ResultData>

Handle to a pooled job or worker submission.

wait() returns the job result, while update and onUpdate expose the most recent progress value published by the child thread.

Properties

status: FutureStatus

Current lifecycle state for this queued or running job.

error: Exception?

Copied exception payload when the job has failed or been cancelled.

update: UpdateData?

Most recent progress value published by the child, if any.

onError: (((future: Future<UpdateData, ResultData>, err: Exception) → ()))?

Optional callback invoked on the parent runtime when the job errors.

onUpdate: (((future: Future<UpdateData, ResultData>, value: UpdateData) → ()))?

Optional callback invoked whenever the child publishes an update.

Future:wait

⚠ Yields

Wait for the job to finish and return its final result.

Future:wait()ResultData

Returns

ResultData

Final value returned by the pooled job.

ThreadPool

Pool of reusable worker slots for ad-hoc thread jobs.

Properties

workers: number

Maximum number of jobs that may run in parallel.

active: number

Number of jobs currently running.

queued: number

Number of jobs currently queued waiting for a free worker slot.

onError: (((future: Future<T, U>, err: Exception) → ()))?

Default error callback for futures created by this pool.

onUpdate: (((future: Future<T, U>, value: T) → ()))?

Default update callback for futures created by this pool.

ThreadPool:spawn

Queue a job to run on the pool and return a future for its result.

ThreadPool:spawn<InitialData, SendData, UpdateData, RecvData, ResultData>(entry: string | ThreadEntryFunction<InitialData, SendData, UpdateData, RecvData, ResultData>, context: InitialData)Future<UpdateData, ResultData>

Parameters

entry: string | ThreadEntryFunction<InitialData, SendData, UpdateData, RecvData, ResultData>

File path or pure Luau function to execute for this job.

context: InitialData

Initial payload exposed to the child as context.value.

Returns

Future<UpdateData, ResultData>

Future that resolves to the job result and receives progress updates.

ThreadWorker<InitialData, UpdateData, ResultData>

Preconfigured worker that reuses the same job entry for every submission.

This is useful when you want pool-like parallelism but do not want to pass the entry function or file path on every call.

Properties

workers: number

Maximum number of jobs that may run in parallel.

active: number

Number of jobs currently running.

queued: number

Number of jobs currently queued waiting for a free worker slot.

onError: (((future: Future<UpdateData, ResultData>, err: Exception) → ()))?

Default error callback for futures created by this worker.

onUpdate: (((future: Future<UpdateData, ResultData>, value: UpdateData) → ()))?

Default update callback for futures created by this worker.

ThreadWorker:submit

Submit one or more payloads to the worker's configured job entry.

When called with one payload, this returns a single future. When called with multiple payloads, it returns an array of futures in the same order as the submitted inputs.

ThreadWorker:submit()Future<UpdateData, ResultData>

Returns

Future<UpdateData, ResultData>

Future when called with one payload, or an array of futures when called with many.

ThreadWorker:submit(...: InitialData){ Future<UpdateData, ResultData> }

Parameters

...: InitialData

One or more initial payloads to run through the worker's job entry.

Returns

{ Future<UpdateData, ResultData> }

Future when called with one payload, or an array of futures when called with many.

Functions

thread.spawn

Spawn a single child thread immediately.

entry may be a file path or a pure Luau function that can be serialized into the child runtime. The returned handle can be used for bidirectional messaging, error observation, and final result collection.

thread.spawn<InitialData, SendData, UpdateData, RecvData, ResultData>(entry: string | ThreadEntryFunction<InitialData, SendData, UpdateData, RecvData, ResultData>, context: InitialData)ThreadHandle<SendData, RecvData, ResultData>

Parameters

entry: string | ThreadEntryFunction<InitialData, SendData, UpdateData, RecvData, ResultData>

File path or pure Luau function to execute in the child runtime.

context: InitialData

Initial payload exposed to the child as context.value.

Returns

ThreadHandle<SendData, RecvData, ResultData>

Handle used to communicate with the child and collect its final result.

thread.cpuCount

Return the number of logical CPUs visible to the host process.

This is a good default upper bound when choosing a pool size for CPU-bound work, though IO-bound workloads may prefer different tuning.

thread.cpuCount()number

Returns

Number of logical CPUs reported by the operating system.

thread.pool

Create a thread pool for running many jobs with bounded concurrency.

Each call to pool:spawn(...) returns a future that resolves when that job completes.

thread.pool(options: PoolOptions)ThreadPool

Parameters

options: PoolOptions

Pool construction options such as worker-count limits.

Returns

Thread pool that queues jobs and runs them with bounded parallelism.

thread.worker

Create a reusable worker with a fixed job entry and bounded concurrency.

Each call to worker:submit(...) reuses the configured job entry and only changes the submitted payload.

thread.worker<InitialData, SendData, UpdateData, RecvData, ResultData>(options: WorkerOptions<InitialData, SendData, UpdateData, RecvData, ResultData>)ThreadWorker<InitialData, UpdateData, ResultData>

Parameters

options: WorkerOptions<InitialData, SendData, UpdateData, RecvData, ResultData>

Worker construction options including the shared job entry.

Returns

ThreadWorker<InitialData, UpdateData, ResultData>

Reusable worker that submits payloads to the configured job entry.

Types

Status

Lifecycle states exposed by a direct thread handle.

type Status = "starting" | "running" | "finished" | "error" | "killed" | "interrupted"

FutureStatus

Lifecycle states exposed by pooled work items.

type FutureStatus = "queued" | "running" | "finished" | "error" | "cancelled"

Exception

Exception payload copied back from a failed child runtime.

type Exception = exception.Exception
Implements: exception.Exception

AnyThreadContext

Untyped alias for child thread contexts.

Implements: ThreadContext

AnyThreadHandle

Untyped alias for direct thread handles.

Implements: ThreadHandle

ThreadEntryFunction<InitialData, SendData, UpdateData, RecvData, ResultData>

Thread entrypoint function.

The generic parameter order is written from the API caller's point of view, but the actual context object flips send/receive directions so the child sees the correct interface:

  • parent SendData becomes child RecvData
  • parent RecvData becomes child SendData
type ThreadEntryFunction<InitialData, SendData, UpdateData, RecvData, ResultData> = ( context: ThreadContext<InitialData, RecvData, UpdateData, SendData> )ResultData

PoolOptions

Options for constructing a thread pool.

type PoolOptions = { workers: number }
workers: number

Maximum number of jobs that may run in parallel.

WorkerOptions<InitialData, SendData, UpdateData, RecvData, ResultData>

Options for constructing a preconfigured thread worker.

type WorkerOptions<InitialData, SendData, UpdateData, RecvData, ResultData> = { workers: number, job: string | ThreadEntryFunction< InitialData, SendData, UpdateData, RecvData, ResultData > }
workers: number

Maximum number of jobs that may run in parallel.

job: string | ThreadEntryFunction<InitialData, SendData, UpdateData, RecvData, ResultData>

Job entry to run for every submission made through this worker.