-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMutex.js
57 lines (47 loc) · 1.4 KB
/
Mutex.js
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
const cache = Symbol("Mutex Cache")
const locks = Symbol("Mutex Locks")
const defer = typeof setImmediate !== "undefined" ? setImmediate : setTimeout
class Mutex {
static [cache] = {};
[locks] = {}
constructor(handle) {
if (typeof Mutex[cache][handle] === "undefined") {
Mutex[cache][handle] = this
} else {
return Mutex[cache][handle]
}
}
static defer() {
return new Promise(defer)
}
[Symbol.asyncIterator]() {
return {
next: async () => {
await Mutex.defer()
return {
value: await this.lock(),
done: false
}
}
}
}
get [Symbol.toStringTag]() {
return "Mutex"
}
lock() {
return new Promise(async (resolve) => {
while (Object.getOwnPropertySymbols(this[locks]).length > 0) {
const key = Object.getOwnPropertySymbols(this[locks]).pop()
await this[locks][key]
await Mutex.defer()
}
const key = Symbol("Mutex Lock")
this[locks][key] = new Promise((unlock) =>
void resolve(() => {
unlock()
delete this[locks][key]
}))
})
}
}
module.exports = Mutex