spica
Version:
Supervisor, Coroutine, Channel, select, AtomicPromise, Cancellation, Cache, List, Queue, Stack, and some utils.
43 lines (41 loc) • 1.32 kB
text/typescript
import { AtomicFuture } from './future';
import { Coroutine, CoroutineOptions } from './coroutine';
import { Queue } from './queue';
export class Colistener<T, U = undefined> extends Coroutine<U, T> {
constructor(
listen: (this: Colistener<T, U>, listener: (value: T) => void) => () => void,
opts: CoroutineOptions = {},
) {
super(async function* (this: Colistener<T, U>) {
const queue = new Queue<T>;
let notifier: AtomicFuture<undefined> = new AtomicFuture();
let notifiable: boolean = true;
this.finally(listen.call(this, (value: T) => {
assert(this[Coroutine.alive]);
if (notifiable) {
notifier.bind();
notifiable = false;
}
queue.push(value);
while (queue.length > (opts.capacity || 1)) {
queue.pop()!;
}
assert(queue.length > 0);
}));
while (true) {
await notifier;
notifier = new AtomicFuture();
notifiable = true;
while (!queue.isEmpty()) {
yield queue.pop()!;
}
}
}, { ...opts, capacity: -1, run: false });
this[Coroutine.init]();
}
public close(this: Colistener<T, undefined>, value?: U): void;
public close(value: U): void;
public close(value: U): void {
this[Coroutine.exit](value);
}
}