UNPKG

@thi.ng/csp

Version:

Primitives & operators for Communicating Sequential Processes based on async/await and async iterables

164 lines 6.26 kB
import type { Fn, Maybe } from "@thi.ng/api"; import type { ChannelBuffer, ChannelValue, IChannel } from "./api.js"; export declare const MAX_READS = 1024; export declare const MAX_WRITES = 1024; export interface ChannelOpts { id: string; } /** * Syntax sugar for creating a new CSP {@link Channel}. By default, the channel * has a buffer capacity of 1 value, but supports custom buffer sizes and/or * implementations (described in readme). * * @param opts */ export declare function channel<T>(opts?: Partial<ChannelOpts>): Channel<T>; export declare function channel<T>(buf: ChannelBuffer<T> | number, opts?: Partial<ChannelOpts>): Channel<T>; export declare class Channel<T> implements IChannel<T> { id: string; writes: ChannelBuffer<T>; queue: ChannelValue<T>[]; reads: Fn<Maybe<T>, void>[]; races: Fn<Channel<T>, void>[]; protected state: number; /** * See {@link channel} for reference. * * @param opts */ constructor(opts?: Partial<ChannelOpts>); constructor(buf: ChannelBuffer<T> | number, opts?: Partial<ChannelOpts>); /** * Returns an async iterator of this channel, acting as adapter between the * CSP world and the more generic ES async iterables. The iterator stops * once the channel has been closed and no further values can be read. * * @remarks * Multiple iterators will compete for new values. To ensure an iterator * receives all of the channel's values, you must either ensure there's only * a single iterator per channel or feed the channel into a {@link mult} * first and create an iterator of a channel obtained via * {@link Mult.subscribe}. * * @example * ```ts tangle:../export/channel-iterator.ts * import { channel } from "@thi.ng/csp"; * * const chan = channel<number>(); * * (async () => { * // implicit iterator conversion of the channel * for await(let x of chan) console.log("received", x); * console.log("channel closed"); * })() * * chan.write(1); * chan.write(2); * chan.write(3); * chan.close(); * ``` */ [Symbol.asyncIterator](): AsyncIterableIterator<T>; /** * Attempts to read a value from the channel. The returned promise will * block until such value becomes available or if the channel has been * closed in the meantime. In that latter case, the promise will resolve to * `undefined`. * * @remarks * If a value is already available at the time of the function call, the * promise resolves immediately. * * Note: There's a limit of in-flight {@link MAX_READS} allowed per channel. * The promise will reject if that number is exceeded. * * Also see {@link Channel.poll}. */ read(): Promise<Maybe<T>>; /** * Similar to {@link Channel.read}, but not async and non-blocking. Will * only succeed if the channel is readable (i.e. not yet closed) and if a * value can be read immediately (without waiting). Returns the value or * `undefined` if unsuccessful. * * @remarks * Use {@link Channel.closed} to check if the channel is already closed. */ poll(): Maybe<T>; /** * Attempts to write a new value to the channel and returns a promise * indicating success or failure. Depending on buffer capacity & behavior, * the returned promise will block until the channel accept new values (i.e. * until the next {@link Channel.read}) or if it has been closed in the * meantime. In that latter case, the promise will resolve to false. * * @remarks * If the channel's buffer accepts new writes or if a read op is already * waiting at the time of the function call, the promise resolves * immediately. * * If the buffer is already full, the write will be queued and only resolve * when delivered. Note: As a fail-safe, there's a limit of queued * {@link MAX_WRITES} allowed per channel. The promise will reject if that * number is exceeded. * * Also see {@link Channel.offer}. */ write(msg: T): Promise<boolean>; /** * Similar to {@link Channel.write}, but not async and non-blocking. Will * only succeed if the channel is writable (i.e. not yet closed/closing) and * if a write is immediately possible (without queuing). Returns true, if * successful. * * @param msg */ offer(msg: T): boolean; /** * Queues a "race" operation & returns a promise which resolves with the * channel itself when the channel becomes readable, but no other queued * read operations are waiting (which always have priority). If the channel * is already closed, the promise resolves immediately. * * @remarks * This op is used internally by {@link select} to choose a channel to read * from next. */ race(): Promise<Channel<T>>; /** * Triggers closing of the channel (idempotent). Any queued writes remain * readable, but new writes will be ignored. * * @remarks * Whilst there're still values available for reading, * {@link Channel.closed} will still return false since the channel state is * still "closing", not yet fully "closed". */ close(): void; /** * Returns true if the channel is principally readable (i.e. not yet * closed), however there might not be any values available yet and reads * might block. */ readable(): boolean; /** * Returns true if the channel is principally writable (i.e. not closing or * closed), however depending on buffer behavior the channel might not yet * accept new values and writes might block. */ writable(): boolean; /** * Returns true if the channel is fully closed and no further reads or * writes are possible. * * @remarks * Whilst there're still values available for reading, this will still * return false since the channel state is still "closing", not yet fully * "closed". */ closed(): boolean; /** @internal */ updateQueue(): void; protected deliver(): void; } //# sourceMappingURL=channel.d.ts.map