UNPKG

async-mutex

Version:
116 lines (115 loc) 4.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var errors_1 = require("./errors"); var Semaphore = /** @class */ (function () { function Semaphore(_value, _cancelError) { if (_cancelError === void 0) { _cancelError = errors_1.E_CANCELED; } this._value = _value; this._cancelError = _cancelError; this._weightedQueues = []; this._weightedWaiters = []; } Semaphore.prototype.acquire = function (weight) { var _this = this; if (weight === void 0) { weight = 1; } if (weight <= 0) throw new Error("invalid weight ".concat(weight, ": must be positive")); return new Promise(function (resolve, reject) { if (!_this._weightedQueues[weight - 1]) _this._weightedQueues[weight - 1] = []; _this._weightedQueues[weight - 1].push({ resolve: resolve, reject: reject }); _this._dispatch(); }); }; Semaphore.prototype.runExclusive = function (callback, weight) { if (weight === void 0) { weight = 1; } return tslib_1.__awaiter(this, void 0, void 0, function () { var _a, value, release; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: return [4 /*yield*/, this.acquire(weight)]; 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 (weight) { var _this = this; if (weight === void 0) { weight = 1; } if (weight <= 0) throw new Error("invalid weight ".concat(weight, ": must be positive")); return new Promise(function (resolve) { if (!_this._weightedWaiters[weight - 1]) _this._weightedWaiters[weight - 1] = []; _this._weightedWaiters[weight - 1].push(resolve); _this._dispatch(); }); }; Semaphore.prototype.isLocked = function () { return this._value <= 0; }; Semaphore.prototype.getValue = function () { return this._value; }; Semaphore.prototype.setValue = function (value) { this._value = value; this._dispatch(); }; Semaphore.prototype.release = function (weight) { if (weight === void 0) { weight = 1; } if (weight <= 0) throw new Error("invalid weight ".concat(weight, ": must be positive")); this._value += weight; this._dispatch(); }; Semaphore.prototype.cancel = function () { var _this = this; this._weightedQueues.forEach(function (queue) { return queue.forEach(function (entry) { return entry.reject(_this._cancelError); }); }); this._weightedQueues = []; }; Semaphore.prototype._dispatch = function () { var _a; for (var weight = this._value; weight > 0; weight--) { var queueEntry = (_a = this._weightedQueues[weight - 1]) === null || _a === void 0 ? void 0 : _a.shift(); if (!queueEntry) continue; var previousValue = this._value; var previousWeight = weight; this._value -= weight; weight = this._value + 1; queueEntry.resolve([previousValue, this._newReleaser(previousWeight)]); } this._drainUnlockWaiters(); }; Semaphore.prototype._newReleaser = function (weight) { var _this = this; var called = false; return function () { if (called) return; called = true; _this.release(weight); }; }; Semaphore.prototype._drainUnlockWaiters = function () { for (var weight = this._value; weight > 0; weight--) { if (!this._weightedWaiters[weight - 1]) continue; this._weightedWaiters[weight - 1].forEach(function (waiter) { return waiter(); }); this._weightedWaiters[weight - 1] = []; } }; return Semaphore; }()); exports.default = Semaphore;