Initial commit

This commit is contained in:
2025-03-07 19:22:02 +01:00
commit 4a98255d83
55743 changed files with 5280367 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
import { __awaiter, __generator } from "tslib";
import Semaphore from './Semaphore';
var Mutex = /** @class */ (function () {
function Mutex(cancelError) {
this._semaphore = new Semaphore(1, cancelError);
}
Mutex.prototype.acquire = function () {
return __awaiter(this, void 0, void 0, function () {
var _a, releaser;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this._semaphore.acquire()];
case 1:
_a = _b.sent(), releaser = _a[1];
return [2 /*return*/, releaser];
}
});
});
};
Mutex.prototype.runExclusive = function (callback) {
return this._semaphore.runExclusive(function () { return callback(); });
};
Mutex.prototype.isLocked = function () {
return this._semaphore.isLocked();
};
Mutex.prototype.waitForUnlock = function () {
return this._semaphore.waitForUnlock();
};
/** @deprecated Deprecated in 0.3.0, will be removed in 0.4.0. Use runExclusive instead. */
Mutex.prototype.release = function () {
this._semaphore.release();
};
Mutex.prototype.cancel = function () {
return this._semaphore.cancel();
};
return Mutex;
}());
export default Mutex;
+1
View File
@@ -0,0 +1 @@
export {};
+100
View File
@@ -0,0 +1,100 @@
import { __awaiter, __generator } from "tslib";
import { E_CANCELED } from './errors';
var Semaphore = /** @class */ (function () {
function Semaphore(_maxConcurrency, _cancelError) {
if (_cancelError === void 0) { _cancelError = 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 __awaiter(this, void 0, void 0, function () {
var _a, value, release;
return __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 __awaiter(this, void 0, void 0, function () {
var waitPromise;
var _this = this;
return __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;
}());
export default Semaphore;
+1
View File
@@ -0,0 +1 @@
export {};
+3
View File
@@ -0,0 +1,3 @@
export var E_TIMEOUT = new Error('timeout while waiting for mutex to become available');
export var E_ALREADY_LOCKED = new Error('mutex already locked');
export var E_CANCELED = new Error('request for lock canceled');
+5
View File
@@ -0,0 +1,5 @@
export { default as Mutex } from './Mutex';
export { default as Semaphore } from './Semaphore';
export { withTimeout } from './withTimeout';
export { tryAcquire } from './tryAcquire';
export * from './errors';
+8
View File
@@ -0,0 +1,8 @@
import { E_ALREADY_LOCKED } from './errors';
import { withTimeout } from './withTimeout';
// eslint-disable-next-lisne @typescript-eslint/explicit-module-boundary-types
export function tryAcquire(sync, alreadyAcquiredError) {
if (alreadyAcquiredError === void 0) { alreadyAcquiredError = E_ALREADY_LOCKED; }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return withTimeout(sync, 0, alreadyAcquiredError);
}
+86
View File
@@ -0,0 +1,86 @@
import { __awaiter, __generator } from "tslib";
import { E_TIMEOUT } from './errors';
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function withTimeout(sync, timeout, timeoutError) {
var _this = this;
if (timeoutError === void 0) { timeoutError = E_TIMEOUT; }
return {
acquire: function () {
return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
var isTimeout, handle, ticket, release, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
isTimeout = false;
handle = setTimeout(function () {
isTimeout = true;
reject(timeoutError);
}, timeout);
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, sync.acquire()];
case 2:
ticket = _a.sent();
if (isTimeout) {
release = Array.isArray(ticket) ? ticket[1] : ticket;
release();
}
else {
clearTimeout(handle);
resolve(ticket);
}
return [3 /*break*/, 4];
case 3:
e_1 = _a.sent();
if (!isTimeout) {
clearTimeout(handle);
reject(e_1);
}
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
}); });
},
runExclusive: function (callback) {
return __awaiter(this, void 0, void 0, function () {
var release, ticket;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
release = function () { return undefined; };
_a.label = 1;
case 1:
_a.trys.push([1, , 7, 8]);
return [4 /*yield*/, this.acquire()];
case 2:
ticket = _a.sent();
if (!Array.isArray(ticket)) return [3 /*break*/, 4];
release = ticket[1];
return [4 /*yield*/, callback(ticket[0])];
case 3: return [2 /*return*/, _a.sent()];
case 4:
release = ticket;
return [4 /*yield*/, callback()];
case 5: return [2 /*return*/, _a.sent()];
case 6: return [3 /*break*/, 8];
case 7:
release();
return [7 /*endfinally*/];
case 8: return [2 /*return*/];
}
});
});
},
/** @deprecated Deprecated in 0.3.0, will be removed in 0.4.0. Use runExclusive instead. */
release: function () {
sync.release();
},
cancel: function () {
return sync.cancel();
},
waitForUnlock: function () { return sync.waitForUnlock(); },
isLocked: function () { return sync.isLocked(); },
};
}