UNPKG

3.82 kBJavaScriptView Raw
1"use strict";
2/*! *****************************************************************************
3Copyright (c) Microsoft Corporation.
4Licensed under the Apache License, Version 2.0.
5
6See LICENSE file in the project root for details.
7***************************************************************************** */
8Object.defineProperty(exports, "__esModule", { value: true });
9const list_1 = require("./list");
10const cancellation_1 = require("./cancellation");
11const utils_1 = require("./utils");
12const adapter_1 = require("./adapter");
13const MAX_INT32 = -1 >>> 1;
14/**
15 * Limits the number of asynchronous operations that can access a resource
16 * or pool of resources.
17 */
18class Semaphore {
19 /**
20 * Initializes a new instance of the Semaphore class.
21 *
22 * @param initialCount The initial number of entries.
23 * @param maxCount The maximum number of entries.
24 */
25 constructor(initialCount, maxCount) {
26 this._waiters = new list_1.LinkedList();
27 if (utils_1.isMissing(maxCount))
28 maxCount = MAX_INT32;
29 if (!utils_1.isNumber(initialCount))
30 throw new TypeError("Number expected: initialCount.");
31 if (!utils_1.isNumber(maxCount))
32 throw new TypeError("Number expected: maxCount.");
33 if ((initialCount |= 0) < 0)
34 throw new RangeError("Argument out of range: initialCount.");
35 if ((maxCount |= 0) < 1)
36 throw new RangeError("Argument out of range: maxCount.");
37 if (initialCount > maxCount)
38 throw new RangeError("Argument out of range: initialCount.");
39 this._currentCount = initialCount;
40 this._maxCount = maxCount;
41 }
42 /**
43 * Gets the number of remaining asynchronous operations that can enter
44 * the Semaphore.
45 */
46 get count() {
47 return this._currentCount;
48 }
49 /**
50 * Asynchronously waits for the event to become signaled.
51 *
52 * @param token A CancellationToken used to cancel the request.
53 */
54 wait(token) {
55 return new Promise((resolve, reject) => {
56 const _token = adapter_1.getToken(token);
57 _token.throwIfCancellationRequested();
58 if (this._currentCount > 0) {
59 this._currentCount--;
60 resolve();
61 return;
62 }
63 const node = this._waiters.push(() => {
64 registration.unregister();
65 if (_token.cancellationRequested) {
66 reject(new cancellation_1.CancelError());
67 }
68 else {
69 resolve();
70 }
71 });
72 const registration = _token.register(() => {
73 if (node.list) {
74 node.list.deleteNode(node);
75 reject(new cancellation_1.CancelError());
76 }
77 });
78 });
79 }
80 /**
81 * Releases the Semaphore one or more times.
82 *
83 * @param count The number of times to release the Semaphore.
84 */
85 release(count) {
86 if (utils_1.isMissing(count))
87 count = 1;
88 if (!utils_1.isNumber(count))
89 throw new TypeError("Number expected: count.");
90 if ((count |= 0) < 1)
91 throw new RangeError("Argument out of range: count.");
92 if (this._maxCount - this._currentCount < count)
93 throw new RangeError("Argument out of range: count.");
94 while (count > 0) {
95 count--;
96 const resolve = this._waiters.shift();
97 if (resolve) {
98 resolve();
99 }
100 else {
101 this._currentCount++;
102 }
103 }
104 }
105}
106exports.Semaphore = Semaphore;