1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | Object.defineProperty(exports, "__esModule", { value: true });
|
7 | exports.Semaphore = void 0;
|
8 | const ral_1 = require("./ral");
|
9 | class Semaphore {
|
10 | constructor(capacity = 1) {
|
11 | if (capacity <= 0) {
|
12 | throw new Error('Capacity must be greater than 0');
|
13 | }
|
14 | this._capacity = capacity;
|
15 | this._active = 0;
|
16 | this._waiting = [];
|
17 | }
|
18 | lock(thunk) {
|
19 | return new Promise((resolve, reject) => {
|
20 | this._waiting.push({ thunk, resolve, reject });
|
21 | this.runNext();
|
22 | });
|
23 | }
|
24 | get active() {
|
25 | return this._active;
|
26 | }
|
27 | runNext() {
|
28 | if (this._waiting.length === 0 || this._active === this._capacity) {
|
29 | return;
|
30 | }
|
31 | (0, ral_1.default)().timer.setImmediate(() => this.doRunNext());
|
32 | }
|
33 | doRunNext() {
|
34 | if (this._waiting.length === 0 || this._active === this._capacity) {
|
35 | return;
|
36 | }
|
37 | const next = this._waiting.shift();
|
38 | this._active++;
|
39 | if (this._active > this._capacity) {
|
40 | throw new Error(`To many thunks active`);
|
41 | }
|
42 | try {
|
43 | const result = next.thunk();
|
44 | if (result instanceof Promise) {
|
45 | result.then((value) => {
|
46 | this._active--;
|
47 | next.resolve(value);
|
48 | this.runNext();
|
49 | }, (err) => {
|
50 | this._active--;
|
51 | next.reject(err);
|
52 | this.runNext();
|
53 | });
|
54 | }
|
55 | else {
|
56 | this._active--;
|
57 | next.resolve(result);
|
58 | this.runNext();
|
59 | }
|
60 | }
|
61 | catch (err) {
|
62 | this._active--;
|
63 | next.reject(err);
|
64 | this.runNext();
|
65 | }
|
66 | }
|
67 | }
|
68 | exports.Semaphore = Semaphore;
|