Spaces:
Runtime error
Runtime error
| ; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| var tslib_1 = require("tslib"); | |
| var errors_1 = require("./errors"); | |
| var Semaphore = /** @class */ (function () { | |
| function Semaphore(_maxConcurrency, _cancelError) { | |
| if (_cancelError === void 0) { _cancelError = errors_1.E_CANCELED; } | |
| this._maxConcurrency = _maxConcurrency; | |
| this._cancelError = _cancelError; | |
| this._queue = []; | |
| this._waiters = []; | |
| if (_maxConcurrency <= 0) { | |
| throw new Error('semaphore must be initialized to a positive value'); | |
| } | |
| this._value = _maxConcurrency; | |
| } | |
| Semaphore.prototype.acquire = function () { | |
| var _this = this; | |
| var locked = this.isLocked(); | |
| var ticketPromise = new Promise(function (resolve, reject) { | |
| return _this._queue.push({ resolve: resolve, reject: reject }); | |
| }); | |
| if (!locked) | |
| this._dispatch(); | |
| return ticketPromise; | |
| }; | |
| Semaphore.prototype.runExclusive = function (callback) { | |
| return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { | |
| var _a, value, release; | |
| return (0, tslib_1.__generator)(this, function (_b) { | |
| switch (_b.label) { | |
| case 0: return [4 /*yield*/, this.acquire()]; | |
| case 1: | |
| _a = _b.sent(), value = _a[0], release = _a[1]; | |
| _b.label = 2; | |
| case 2: | |
| _b.trys.push([2, , 4, 5]); | |
| return [4 /*yield*/, callback(value)]; | |
| case 3: return [2 /*return*/, _b.sent()]; | |
| case 4: | |
| release(); | |
| return [7 /*endfinally*/]; | |
| case 5: return [2 /*return*/]; | |
| } | |
| }); | |
| }); | |
| }; | |
| Semaphore.prototype.waitForUnlock = function () { | |
| return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { | |
| var waitPromise; | |
| var _this = this; | |
| return (0, tslib_1.__generator)(this, function (_a) { | |
| if (!this.isLocked()) { | |
| return [2 /*return*/, Promise.resolve()]; | |
| } | |
| waitPromise = new Promise(function (resolve) { return _this._waiters.push({ resolve: resolve }); }); | |
| return [2 /*return*/, waitPromise]; | |
| }); | |
| }); | |
| }; | |
| Semaphore.prototype.isLocked = function () { | |
| return this._value <= 0; | |
| }; | |
| /** @deprecated Deprecated in 0.3.0, will be removed in 0.4.0. Use runExclusive instead. */ | |
| Semaphore.prototype.release = function () { | |
| if (this._maxConcurrency > 1) { | |
| throw new Error('this method is unavailable on semaphores with concurrency > 1; use the scoped release returned by acquire instead'); | |
| } | |
| if (this._currentReleaser) { | |
| var releaser = this._currentReleaser; | |
| this._currentReleaser = undefined; | |
| releaser(); | |
| } | |
| }; | |
| Semaphore.prototype.cancel = function () { | |
| var _this = this; | |
| this._queue.forEach(function (ticket) { return ticket.reject(_this._cancelError); }); | |
| this._queue = []; | |
| }; | |
| Semaphore.prototype._dispatch = function () { | |
| var _this = this; | |
| var nextTicket = this._queue.shift(); | |
| if (!nextTicket) | |
| return; | |
| var released = false; | |
| this._currentReleaser = function () { | |
| if (released) | |
| return; | |
| released = true; | |
| _this._value++; | |
| _this._resolveWaiters(); | |
| _this._dispatch(); | |
| }; | |
| nextTicket.resolve([this._value--, this._currentReleaser]); | |
| }; | |
| Semaphore.prototype._resolveWaiters = function () { | |
| this._waiters.forEach(function (waiter) { return waiter.resolve(); }); | |
| this._waiters = []; | |
| }; | |
| return Semaphore; | |
| }()); | |
| exports.default = Semaphore; | |