@lightningjs/threadx
Version:
A web browser-based JavaScript library that helps manage the communcation of data between one or more web worker threads.
157 lines (156 loc) • 6.1 kB
TypeScript
import { SharedObject } from './SharedObject.js';
interface ThreadXOptions {
/**
* The ID of the worker. Must be unique across all workers.
*
* Should be an integer value between 1 and 899.
*
* @internalRemarks
* The reason for the 899 limit is the way we generate unique IDs for
* BufferStructs. See `BufferStruct.ts` for more details.
*/
workerId: number;
workerName: string;
sharedObjectFactory?: (buffer: SharedArrayBuffer) => SharedObject | null;
onObjectShared?: (sharedObject: SharedObject) => void;
onBeforeObjectForgotten?: (sharedObject: SharedObject) => void;
onMessage?: (message: any) => Promise<any>;
}
declare global {
class DedicatedWorkerGlobalScope {
DedicatedWorkerGlobalScope: typeof DedicatedWorkerGlobalScope;
postMessage(message: any, transfer?: Transferable[]): void;
addEventListener<K extends keyof WindowEventHandlersEventMap>(type: K, listener: (this: WindowEventHandlers, ev: WindowEventHandlersEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void;
}
interface WindowOrWorkerGlobalScope {
THREADX?: ThreadX;
DedicatedWorkerGlobalScope?: typeof DedicatedWorkerGlobalScope;
}
}
/**
* Created to define a common interface for both Worker parents (`self`) and
* Worker instances
*/
interface WorkerCommon {
postMessage(message: any, transfer?: Transferable[]): void;
addEventListener<K extends keyof WindowEventHandlersEventMap>(type: K, listener: (this: WindowEventHandlers, ev: WindowEventHandlersEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void;
terminate?(): void;
}
interface ForgetOptions {
/**
* If true, no warning will be logged if the object is not found.
*/
silent?: boolean;
}
export declare class ThreadX {
static init(options: ThreadXOptions): ThreadX;
static destroy(): void;
/**
* Get the Worker ID of the current worker
*
* @remarks
* This is only valid after ThreadX.init() has been called.
*/
static get workerId(): number;
/**
* Get the Worker Name of the current thread
*
* @remarks
* This is only valid after ThreadX.init() has been called.
*/
static get workerName(): string;
static get instance(): ThreadX;
readonly workerId: number;
readonly workerName: string;
readonly sharedObjectFactory?: (buffer: SharedArrayBuffer) => SharedObject | null;
private readonly onSharedObjectCreated?;
private readonly onBeforeObjectForgotten?;
/**
* User-defined message handler
*/
private readonly onUserMessage?;
readonly sharedObjects: Map<number, SharedObject>;
/**
* WeakMap of SharedObjects to additional metadata
*/
private sharedObjectData;
readonly workers: Map<string, WorkerCommon>;
private workerReadyPromises;
private pendingAsyncMsgs;
private nextAsyncMsgId;
private nextUniqueId;
/**
* Suppress emitting events from SharedObjects
*
* @remarks
* This is used to prevent infinite loops when emitting events from a SharedObject
* that is shared with another worker.
*
* We set this to true when we receive a SharedObjectEmitMessage from another worker
* and set it back to false after we have emitted the event on the SharedObject.
*/
private suppressSharedObjectEmit;
private constructor();
registerWorker(workerName: string, worker: WorkerCommon): void;
closeWorker(workerName: string): void;
closeWorkerAsync(workerName: string, timeout?: number): Promise<'graceful' | 'forced'>;
private listenForWorkerMessages;
/**
* Share a SharedObject with a worker
*
* @param workerName Worker to share with
* @param sharedObject
*/
shareObjects(workerName: string, sharedObjects: SharedObject[]): Promise<void>;
/**
* Tell ThreadX to forget about SharedObjects
*
* @remarks
* This causes ThreadX on the current worker and the worker that the object
* is shared with to forget about the object. It is up to the worker code to
* actually make sure that no other references to the SharedObjects exist so
* that they can be garbage collected.
*
* A worker can implement the onObjectForgotten() callback to be notified
* when a SharedObject is forgotten.
*
* @param sharedObject
* @param options Options
*/
forgetObjects(sharedObjects: SharedObject[], options?: ForgetOptions): Promise<void>;
sendMessage(workerName: string, message: Record<string, unknown>, transfer?: Transferable[] | undefined): void;
sendMessageAsync(workerName: string, message: Record<string, unknown>, transfer?: Transferable[] | undefined, options?: {
skipResponseWait?: boolean;
}): Promise<any>;
private onMessage;
getSharedObjectById(id: number): SharedObject | null;
/**
* Generates an ID that is unique across all ThreadX workers.
*
* @remarks
* The ID is based on the `workerId` set in the `ThreadXOptions` and an
* incrementing counter. For the ID to actually be unique the `workerId` must
* also be unique.
*
* @returns A unique ID
*/
generateUniqueId(): number;
/**
* Emit an event from a SharedObject to all other workers
*
* @internalRemarks
* For internal ThreadX use only.
*
* Since we aren't sure what workers are sharing a SharedObject we need to
* emit the event to all workers. (TODO: Possible optimization?)
*
* @param sharedObject
* @param eventName
* @param data
* @returns
*/
__sharedObjectEmit(sharedObject: SharedObject, eventName: string, data: Record<string, unknown>): void;
}
export {};