@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
TypeScript
/**
* 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