All files signal.ts

82.92% Statements 34/41
100% Branches 2/2
82.6% Functions 19/23
84.84% Lines 28/33

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 871x         1x 5x     15x 15x 13x 13x               3x 3x             2x 2x               1x     1x   1x 1x     1x 10x 10x 10x               12x 12x   12x 10x 10x     12x 11x 2x 2x                                    
import { Mutex } from "./mutex"
 
/**
 * A class to manage the flow of coroutines using signals.
 */
export class Signal {
	private callback: () => Promise<void> = () => Promise.resolve()
 
	private chain(f: () => Promise<void>): void {
		const callback = this.callback
		this.callback = async () => {
			await callback()
			await f()
		}
	}
 
	/**
	 * Send a signal.
	 */
	public async notify(): Promise<void> {
		await this.callback()
		this.callback = () => Promise.resolve()
	}
 
	/**
	 * Wait until a signal is send.
	 */
	public wait(): Promise<void> {
		return new Promise(resolve => {
			this.chain(async () => resolve())
		})
	}
 
	/**
	 * Repeat a function until a signal is send.
	 */
	public async repeat(
		f: (cancel: Signal) => Promise<void>,
		timeout = 0
	): Promise<void> {
		let cancelled = false
 
		this.chain(async () => {
			cancelled = true
		})
 
		while (!cancelled) {
			const timeout_p = this.timeout(timeout)
			await f(this)
			await timeout_p
		}
	}
 
	/**
	 * Wait for a given time period unless a signal is send.
	 */
	public timeout(time: number): Promise<void> {
		return new Promise<void>(resolve => {
			let finished = false
 
			const timeout = setTimeout(() => {
				finished = true
				resolve()
			}, time)
 
			this.chain(async () => {
				if (!finished) {
					clearTimeout(timeout)
					resolve()
				}
			})
		})
	}
 
	async while(f: (stop: Mutex) => Promise<void>): Promise<void> {
		const stop = new Mutex()
 
		this.chain(async () => {
			stop.set(true)
		})
 
		while (!stop.get()) {
			await f(stop)
		}
	}
}