Skip to content

Instantly share code, notes, and snippets.

@iwasaki-kenta
Last active August 25, 2021 03:32
Show Gist options
  • Save iwasaki-kenta/a3eff0bfbbb4974d33517ecf500b69de to your computer and use it in GitHub Desktop.
Save iwasaki-kenta/a3eff0bfbbb4974d33517ecf500b69de to your computer and use it in GitHub Desktop.
Go-like channels in TypeScript.
export class Deferred<T> {
promise: Promise<T>;
resolve: (value?: T | PromiseLike<T>) => void;
reject: (reason?: any) => void;
constructor() {
this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}
}
export class Channel<T> {
public constructor(
public readonly capacity = 0,
private readonly values: Array<T> = [],
private readonly sends: Array<{ value: T, signal: Deferred<void> }> = [],
private readonly recvs: Array<Deferred<T>> = [],
) {
}
public async send(value): Promise<void> {
if (this.recvs.length > 0) {
this.recvs.shift().resolve(value);
return;
}
if (this.values.length < this.capacity) {
this.values.push(value);
return;
}
const signal = new Deferred<void>();
this.sends.push({value, signal});
await signal.promise;
}
public async recv(): Promise<T> {
if (this.values.length > 0) return this.values.shift();
if (this.sends.length > 0) {
const send = this.sends.shift();
send.signal.resolve();
return send.value;
}
const signal = new Deferred<T>();
this.recvs.push(signal);
return await signal.promise;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment