UNPKG

2.32 kBJavaScriptView Raw
1//@flow
2
3import Module from './Module'
4
5const { MODULE_NAME, log, warn, error } = new Module(__filename) // eslint-disable-line no-unused-vars
6
7export class OneTimeBroadcastEvent {
8
9 _waitingList: Array<() => void>
10 signaled: boolean
11
12
13 constructor(signaledInitially: boolean) {
14 this._waitingList = []
15 this.signaled = signaledInitially
16 }
17
18
19 wait = async (): Promise<void> => {
20 if (this.signaled)
21 return
22 await new Promise(res => this._waitingList.push(res))
23 }
24
25 signal = (): void => {
26 this._waitingList.forEach(res => res())
27 this.signaled = true
28 }
29
30 reset = (): void => {
31 this.signaled = false
32 }
33}
34
35export class Semaphore {
36
37 _waitingList: Array<() => void>
38 _maxCapacity: number
39 _name: ?string
40
41 takenCount: number
42
43 constructor(maxCapacity: number, name: ?string) {
44 this._maxCapacity = maxCapacity
45 this._waitingList = []
46 this._name = name
47 this._name && log(`Semaphore was created`, { name: this._name, maxCapacity: maxCapacity })
48 this.takenCount = 0
49 }
50
51
52 enter = async (): Promise<void> => {
53 if (this.takenCount >= this._maxCapacity) {
54 this._name && log(`Semaphore is awaited`, { name: this._name, takenCount: this.takenCount })
55 await new Promise(res => this._waitingList.push(res))
56 this._name && log(`Semaphore awaiting completed`, { name: this._name, takenCount: this.takenCount })
57 }
58 this.takenCount++
59 this._name && log(`Semaphore was entered`, { name: this._name, takenCount: this.takenCount })
60 }
61
62 exit = (): void => {
63 this._waitingList.length && this._waitingList.shift()()
64 if (this.takenCount > 0)
65 this.takenCount--
66 this._name && log(`Semaphore was exited`, { name: this._name, takenCount: this.takenCount })
67 }
68
69 async run<T>(asyncFunc: () => Promise<T>): Promise<T> {
70 try {
71 await this.enter()
72 return await asyncFunc()
73 } finally {
74 this.exit()
75 }
76 }
77
78 async runConditional(asyncFunc: () => Promise<void>, condition: () => boolean): Promise<void> {
79 if (!condition || condition()) {
80 try {
81 await this.enter()
82 if (!condition || condition()) {
83 await asyncFunc()
84 }
85 } finally {
86 this.exit()
87 }
88 }
89 }
90}
91
92export class CriticalSection extends Semaphore {
93 constructor() {
94 super(1)
95 }
96}
\No newline at end of file