UNPKG

@sp8d/core

Version:

sp8d-core: Ultra-low latency, memory-safe concurrency primitives for TypeScript/JavaScript. Lock-free channels with comprehensive safety guarantees, race condition prevention, and zero-copy messaging for browser and Node.js applications.

184 lines 6.63 kB
/** * Ultra-low-latency, lock-free channel for concurrent message passing. * @remarks Use `createChannel` to construct. For advanced diagnostics, see exposed readonly arrays. */ export type Mode = "SPSC" | "MPSC" | "MPMC"; export interface ChannelStats { slots: number; used: number; free: number; stalled: number; errors: number; conflicts: number; reclaimed: number; } export interface Channel extends AsyncIterable<Uint8Array> { send(payload: ArrayBufferView, producerId?: number): boolean; recv(): Uint8Array | null; recvAsync(): Promise<Uint8Array | null>; sendJSON?(obj: object, producerId?: number): boolean; recvJSON?(): object | null; full(): boolean; empty(): boolean; close(): void; stats(): ChannelStats; info(): string; validate(): void; [Symbol.asyncIterator](): AsyncIterator<Uint8Array, void>; } declare class SegmentMeta { head: Int32Array; tail: Int32Array; count: Int32Array; constructor(base: number, sab: SharedArrayBuffer, slots: number); } export declare class ChannelCore implements Channel { /** SharedArrayBuffer backing this channel. */ private readonly sab; /** Segment metadata (head, tail, count) for each segment. */ readonly segmentMetas: SegmentMeta[]; /** Slot status arrays (diagnostics only, readonly). */ readonly slotStatus: Uint8Array[]; /** Slot generation/cycle tag arrays (diagnostics only, readonly). */ readonly slotGeneration: Uint8Array[]; /** Slot claim timestamp arrays (diagnostics only, readonly). */ readonly slotClaimTimestamp: Uint32Array[]; /** Slot payload arrays (internal use). */ private readonly payload; private readonly slots; private readonly segments; private readonly messageSize; private readonly mode; private errors; private conflicts; private reclaimed; private closed; private sweepTimeoutMs; private sweeperInterval; private readonly meta; constructor(sab: SharedArrayBuffer, slots: number, slotSize: number, mode?: Mode, segments?: number, sweepTimeoutMs?: number); static fromBuffer(sab: SharedArrayBuffer): ChannelCore; /** * Get a monotonic timestamp that handles 32-bit overflow gracefully. * This prevents wraparound issues in long-running applications. * @returns 32-bit timestamp value */ private getMonotonicTimestamp; private pickSegment; /** * Send a message. Throws if the channel is full or payload is too large. * @param payload Message to send (ArrayBufferView) * @param producerId Optional producer ID for multi-segment routing * @returns true if sent, throws otherwise */ send(payload: ArrayBufferView, producerId?: number): boolean; /** * Try to send a message. Returns false if the channel is full or payload is too large. * @param payload Message to send (ArrayBufferView) * @param producerId Optional producer ID for multi-segment routing * @returns true if sent, false otherwise */ trySend(payload: ArrayBufferView, producerId?: number): boolean; /** * Send a JSON-serializable object. Throws if the channel is full or payload is too large. * @param obj Object to send * @param producerId Optional producer ID for multi-segment routing * @returns true if sent, throws otherwise */ sendJSON(obj: object, producerId?: number): boolean; /** * Receive a message. Returns null if the channel is empty. * @returns Uint8Array or null */ recv(): Uint8Array | null; /** * Try to receive a message. Returns null if the channel is empty. * @returns Uint8Array or null */ tryRecv(): Uint8Array | null; /** * Receive a JSON-serialized object. Returns null if the channel is empty or parse fails. * @returns object or null */ recvJSON(): object | null; /** * Async iterator for receiving messages. */ [Symbol.asyncIterator](): AsyncIterator<Uint8Array, void>; /** * Receive a message asynchronously. Resolves when a message is available or channel is closed. * @returns Promise<Uint8Array | null> */ recvAsync(): Promise<Uint8Array | null>; /** * Returns true if the channel is full. */ full(): boolean; /** * Returns true if the channel is empty. */ empty(): boolean; /** * Close the channel and stop all background tasks. */ close(): void; /** * Asynchronously close the channel, waiting for all background tasks to stop. * @returns Promise<void> */ closeAsync(): Promise<void>; /** * Reset the channel to its initial state (empties all slots, resets counters). * Does not reallocate the buffer. */ reset(): void; /** * Get current channel statistics. */ stats(): ChannelStats; /** * Get a human-readable info string for this channel. */ info(): string; /** * Validate the channel's internal state. Throws if protocol invariants are violated. */ validate(): void; private sweepStaleSlots; /** * Send a message asynchronously. Waits until a slot is available or timeout/abort. * Uses polling for browser compatibility (Atomics.wait is not available on main thread). * Never queues messages internally; each call only waits for a slot, then sends. * @param payload Message to send (ArrayBufferView) * @param producerId Optional producer ID for multi-segment routing * @param opts Optional: { timeoutMs?: number, signal?: AbortSignal } * @returns Promise<boolean> Resolves true if sent, false if timeout/abort */ sendAsync(payload: ArrayBufferView, producerId?: number, opts?: { timeoutMs?: number; signal?: AbortSignal; }): Promise<boolean>; } /** * Create a new SP8D channel with the specified options. * @param options Channel configuration options * @returns Object containing the channel instance and SharedArrayBuffer */ export declare function createChannel(options: { slots: number; slotSize: number; mode?: Mode; segments?: number; sweepTimeoutMs?: number; }): { channel: Channel; buffer: SharedArrayBuffer; }; /** * Attach to an existing SP8D channel using its SharedArrayBuffer. * @param buffer The SharedArrayBuffer from a previously created channel * @returns Channel instance attached to the existing buffer */ export declare function attachChannel(buffer: SharedArrayBuffer): Channel; export {}; //# sourceMappingURL=sp8d-core.d.ts.map