remove node_modules and .gitignore them
This commit is contained in:
-80
@@ -1,80 +0,0 @@
|
||||
/**
|
||||
* Barrier for critical sections.
|
||||
*
|
||||
* The Barrier class blocks critical sections until the downward counter to be zero. Unlike the
|
||||
* {@link Latch} class whose downward counter is disposable, `Barrier` can re-use the downward
|
||||
* counter repeatedly, resetting counter to be initial value whenever reach to the zero.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class Barrier {
|
||||
private cv_;
|
||||
private size_;
|
||||
private count_;
|
||||
/**
|
||||
* Initializer Constructor
|
||||
*
|
||||
* @param size Size of the downward counter.
|
||||
*/
|
||||
constructor(size: number);
|
||||
/**
|
||||
* Waits until the counter to be zero.
|
||||
*
|
||||
* Blocks the function calling until internal counter to be reached to the zero.
|
||||
*/
|
||||
wait(): Promise<void>;
|
||||
/**
|
||||
* Tries to wait until the counter to be zero in timeout.
|
||||
*
|
||||
* Attempts to block the function calling until internal counter to be reached to the zero
|
||||
* in timeout. If succeeded to waiting the counter to be reached to the zero, it returns
|
||||
* `true`. Otherwise, the {@link Barrier} fails to reach to the zero in the given time, the
|
||||
* function gives up the waiting and returns `false`.
|
||||
*
|
||||
* @param ms The maximum miliseconds for waiting.
|
||||
* @return Whether succeeded to waiting in the given time.
|
||||
*/
|
||||
wait_for(ms: number): Promise<boolean>;
|
||||
/**
|
||||
* Tries to wait until the counter to be zero in time expiration.
|
||||
*
|
||||
* Attempts to block the function calling until internal counter to be reached to the zero
|
||||
* in time expiration. If succeeded to waiting the counter to be reached to the zero, it
|
||||
* returns `true`. Otherwise, the {@link Barrier} fails to reach to the zero in the given
|
||||
* time, the function gives up the waiting and returns `false`.
|
||||
*
|
||||
* @param at The maximum time point to wait.
|
||||
* @return Whether succeeded to waiting in the given time.
|
||||
*/
|
||||
wait_until(at: Date): Promise<boolean>;
|
||||
/**
|
||||
* Derecements the counter.
|
||||
*
|
||||
* Decrements the counter by *n* without blocking.
|
||||
*
|
||||
* If the parametric value *n* is equal to or greater than internal counter, so that the
|
||||
* internal counter be equal to or less than zero, everyone who are {@link wait waiting} for
|
||||
* the {@link Latch} would continue their executions.
|
||||
*
|
||||
* @param n Value of the decrement. Default is 1.
|
||||
*/
|
||||
arrive(n?: number): Promise<void>;
|
||||
/**
|
||||
* Decrements the counter and waits until the counter to be zero.
|
||||
*
|
||||
* Decrements the counter by one and blocks the section until internal counter to be zero.
|
||||
*
|
||||
* If the the remained counter be zero by this decrement, everyone who are
|
||||
* {@link wait waiting} for the {@link Barrier} would continue their executions including
|
||||
* this one.
|
||||
*/
|
||||
arrive_and_wait(): Promise<void>;
|
||||
/**
|
||||
* Decrements the counter and initial size at the same time.
|
||||
*
|
||||
* Decrements not only internal counter, but also initialize size of the counter at the same
|
||||
* time. If the remained counter be zero by the decrement, everyone who are
|
||||
* {@link wait waiting} for the {@link Barrier} would continue their executions.
|
||||
*/
|
||||
arrive_and_drop(): Promise<void>;
|
||||
}
|
||||
-187
@@ -1,187 +0,0 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Barrier = void 0;
|
||||
//================================================================
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
//================================================================
|
||||
var ConditionVariable_1 = require("./ConditionVariable");
|
||||
/**
|
||||
* Barrier for critical sections.
|
||||
*
|
||||
* The Barrier class blocks critical sections until the downward counter to be zero. Unlike the
|
||||
* {@link Latch} class whose downward counter is disposable, `Barrier` can re-use the downward
|
||||
* counter repeatedly, resetting counter to be initial value whenever reach to the zero.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var Barrier = /** @class */ (function () {
|
||||
/**
|
||||
* Initializer Constructor
|
||||
*
|
||||
* @param size Size of the downward counter.
|
||||
*/
|
||||
function Barrier(size) {
|
||||
this.cv_ = new ConditionVariable_1.ConditionVariable();
|
||||
this.size_ = size;
|
||||
this.count_ = size;
|
||||
}
|
||||
/* ---------------------------------------------------------
|
||||
WAIT FUNCTIONS
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* Waits until the counter to be zero.
|
||||
*
|
||||
* Blocks the function calling until internal counter to be reached to the zero.
|
||||
*/
|
||||
Barrier.prototype.wait = function () {
|
||||
return this.cv_.wait();
|
||||
};
|
||||
/**
|
||||
* Tries to wait until the counter to be zero in timeout.
|
||||
*
|
||||
* Attempts to block the function calling until internal counter to be reached to the zero
|
||||
* in timeout. If succeeded to waiting the counter to be reached to the zero, it returns
|
||||
* `true`. Otherwise, the {@link Barrier} fails to reach to the zero in the given time, the
|
||||
* function gives up the waiting and returns `false`.
|
||||
*
|
||||
* @param ms The maximum miliseconds for waiting.
|
||||
* @return Whether succeeded to waiting in the given time.
|
||||
*/
|
||||
Barrier.prototype.wait_for = function (ms) {
|
||||
return this.cv_.wait_for(ms);
|
||||
};
|
||||
/**
|
||||
* Tries to wait until the counter to be zero in time expiration.
|
||||
*
|
||||
* Attempts to block the function calling until internal counter to be reached to the zero
|
||||
* in time expiration. If succeeded to waiting the counter to be reached to the zero, it
|
||||
* returns `true`. Otherwise, the {@link Barrier} fails to reach to the zero in the given
|
||||
* time, the function gives up the waiting and returns `false`.
|
||||
*
|
||||
* @param at The maximum time point to wait.
|
||||
* @return Whether succeeded to waiting in the given time.
|
||||
*/
|
||||
Barrier.prototype.wait_until = function (at) {
|
||||
return this.cv_.wait_until(at);
|
||||
};
|
||||
/* ---------------------------------------------------------
|
||||
ARRIVAL FUNCTIONS
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* Derecements the counter.
|
||||
*
|
||||
* Decrements the counter by *n* without blocking.
|
||||
*
|
||||
* If the parametric value *n* is equal to or greater than internal counter, so that the
|
||||
* internal counter be equal to or less than zero, everyone who are {@link wait waiting} for
|
||||
* the {@link Latch} would continue their executions.
|
||||
*
|
||||
* @param n Value of the decrement. Default is 1.
|
||||
*/
|
||||
Barrier.prototype.arrive = function (n) {
|
||||
if (n === void 0) { n = 1; }
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var completed;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
completed = (this.count_ += n) <= this.size_;
|
||||
if (completed === false)
|
||||
return [2 /*return*/];
|
||||
this.count_ %= this.size_;
|
||||
return [4 /*yield*/, this.cv_.notify_all()];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Decrements the counter and waits until the counter to be zero.
|
||||
*
|
||||
* Decrements the counter by one and blocks the section until internal counter to be zero.
|
||||
*
|
||||
* If the the remained counter be zero by this decrement, everyone who are
|
||||
* {@link wait waiting} for the {@link Barrier} would continue their executions including
|
||||
* this one.
|
||||
*/
|
||||
Barrier.prototype.arrive_and_wait = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, this.arrive()];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [4 /*yield*/, this.wait()];
|
||||
case 2:
|
||||
_a.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Decrements the counter and initial size at the same time.
|
||||
*
|
||||
* Decrements not only internal counter, but also initialize size of the counter at the same
|
||||
* time. If the remained counter be zero by the decrement, everyone who are
|
||||
* {@link wait waiting} for the {@link Barrier} would continue their executions.
|
||||
*/
|
||||
Barrier.prototype.arrive_and_drop = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
--this.size_;
|
||||
return [4 /*yield*/, this.arrive(0)];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
return Barrier;
|
||||
}());
|
||||
exports.Barrier = Barrier;
|
||||
//# sourceMappingURL=Barrier.js.map
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
/**
|
||||
* Condition variable.
|
||||
*
|
||||
* The `ConditionVariable` class blocks critical sections until be notified.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class ConditionVariable {
|
||||
private resolvers_;
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
constructor();
|
||||
/**
|
||||
* Wait until notified.
|
||||
*/
|
||||
wait(): Promise<void>;
|
||||
/**
|
||||
* Wait until predicator returns true.
|
||||
*
|
||||
* This method is equivalent to:
|
||||
*
|
||||
```typescript
|
||||
while (!await predicator())
|
||||
await this.wait();
|
||||
```
|
||||
*
|
||||
* @param predicator A predicator function determines completion.
|
||||
*/
|
||||
wait(predicator: ConditionVariable.Predicator): Promise<void>;
|
||||
/**
|
||||
* Wait for timeout or until notified.
|
||||
*
|
||||
* @param ms The maximum miliseconds for waiting.
|
||||
* @return Whether awaken by notification or timeout.
|
||||
*/
|
||||
wait_for(ms: number): Promise<boolean>;
|
||||
/**
|
||||
* Wait until timeout or predicator returns true.
|
||||
*
|
||||
* This method is equivalent to:
|
||||
```typescript
|
||||
const at: Date = new Date(Date.now() + ms);
|
||||
while (!await predicator())
|
||||
{
|
||||
if (!await this.wait_until(at))
|
||||
return await predicator();
|
||||
}
|
||||
return true;
|
||||
```
|
||||
*
|
||||
* @param ms The maximum miliseconds for waiting.
|
||||
* @param predicator A predicator function determines the completion.
|
||||
* @return Returned value of the *predicator*.
|
||||
*/
|
||||
wait_for(ms: number, predicator: ConditionVariable.Predicator): Promise<boolean>;
|
||||
/**
|
||||
* Wait until notified or time expiration.
|
||||
*
|
||||
* @param at The maximum time point to wait.
|
||||
* @return Whether awaken by notification or time expiration.
|
||||
*/
|
||||
wait_until(at: Date): Promise<boolean>;
|
||||
/**
|
||||
* Wait until time expiration or predicator returns true.
|
||||
*
|
||||
* This method is equivalent to:
|
||||
```typescript
|
||||
while (!await predicator())
|
||||
{
|
||||
if (!await this.wait_until(at))
|
||||
return await predicator();
|
||||
}
|
||||
return true;
|
||||
```
|
||||
*
|
||||
* @param at The maximum time point to wait.
|
||||
* @param predicator A predicator function determines the completion.
|
||||
* @return Returned value of the *predicator*.
|
||||
*/
|
||||
wait_until(at: Date, predicator: ConditionVariable.Predicator): Promise<boolean>;
|
||||
private _Wait;
|
||||
private _Wait_until;
|
||||
/**
|
||||
* Notify, wake only one up.
|
||||
*/
|
||||
notify_one(): Promise<void>;
|
||||
/**
|
||||
* Notify, wake all up.
|
||||
*/
|
||||
notify_all(): Promise<void>;
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export declare namespace ConditionVariable {
|
||||
/**
|
||||
* Type of predicator function who determines the completion.
|
||||
*/
|
||||
type Predicator = () => boolean | Promise<boolean>;
|
||||
}
|
||||
-209
@@ -1,209 +0,0 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var __values = (this && this.__values) || function(o) {
|
||||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
||||
if (m) return m.call(o);
|
||||
if (o && typeof o.length === "number") return {
|
||||
next: function () {
|
||||
if (o && i >= o.length) o = void 0;
|
||||
return { value: o && o[i++], done: !o };
|
||||
}
|
||||
};
|
||||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ConditionVariable = void 0;
|
||||
//================================================================
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
//================================================================
|
||||
var List_1 = require("../container/List");
|
||||
var global_1 = require("./global");
|
||||
/**
|
||||
* Condition variable.
|
||||
*
|
||||
* The `ConditionVariable` class blocks critical sections until be notified.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var ConditionVariable = /** @class */ (function () {
|
||||
/* ---------------------------------------------------------
|
||||
CONSTRUCTORS
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
function ConditionVariable() {
|
||||
this.resolvers_ = new List_1.List();
|
||||
}
|
||||
ConditionVariable.prototype.wait = function (predicator) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
if (!!predicator) return [3 /*break*/, 2];
|
||||
return [4 /*yield*/, this._Wait()];
|
||||
case 1: return [2 /*return*/, _a.sent()];
|
||||
case 2: return [4 /*yield*/, predicator()];
|
||||
case 3:
|
||||
if (!!(_a.sent())) return [3 /*break*/, 5];
|
||||
return [4 /*yield*/, this._Wait()];
|
||||
case 4:
|
||||
_a.sent();
|
||||
return [3 /*break*/, 2];
|
||||
case 5: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
ConditionVariable.prototype.wait_for = function (ms, predicator) {
|
||||
var at = new Date(Date.now() + ms);
|
||||
return this.wait_until(at, predicator);
|
||||
};
|
||||
ConditionVariable.prototype.wait_until = function (at, predicator) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
if (!!predicator) return [3 /*break*/, 2];
|
||||
return [4 /*yield*/, this._Wait_until(at)];
|
||||
case 1: return [2 /*return*/, _a.sent()];
|
||||
case 2: return [4 /*yield*/, predicator()];
|
||||
case 3:
|
||||
if (!!(_a.sent())) return [3 /*break*/, 7];
|
||||
return [4 /*yield*/, this._Wait_until(at)];
|
||||
case 4:
|
||||
if (!!(_a.sent())) return [3 /*break*/, 6];
|
||||
return [4 /*yield*/, predicator()];
|
||||
case 5: return [2 /*return*/, _a.sent()];
|
||||
case 6: return [3 /*break*/, 2];
|
||||
case 7: return [2 /*return*/, true];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
ConditionVariable.prototype._Wait = function () {
|
||||
var _this = this;
|
||||
return new Promise(function (resolve) {
|
||||
_this.resolvers_.push_back({
|
||||
handler: resolve,
|
||||
lockType: 0 /* LockType.HOLD */,
|
||||
});
|
||||
});
|
||||
};
|
||||
ConditionVariable.prototype._Wait_until = function (at) {
|
||||
var _this = this;
|
||||
return new Promise(function (resolve) {
|
||||
var it = _this.resolvers_.insert(_this.resolvers_.end(), {
|
||||
handler: resolve,
|
||||
lockType: 1 /* LockType.KNOCK */,
|
||||
});
|
||||
// AUTOMATIC UNLOCK
|
||||
(0, global_1.sleep_until)(at).then(function () {
|
||||
if (it.erased_ === true)
|
||||
return;
|
||||
// DO UNLOCK
|
||||
_this.resolvers_.erase(it); // POP THE LISTENER
|
||||
resolve(false); // RETURN FAILURE
|
||||
});
|
||||
});
|
||||
};
|
||||
/* ---------------------------------------------------------
|
||||
NOTIFIERS
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* Notify, wake only one up.
|
||||
*/
|
||||
ConditionVariable.prototype.notify_one = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var it;
|
||||
return __generator(this, function (_a) {
|
||||
// NOTHING TO NOTIFY
|
||||
if (this.resolvers_.empty())
|
||||
return [2 /*return*/];
|
||||
it = this.resolvers_.begin();
|
||||
this.resolvers_.erase(it);
|
||||
// CALL ITS HANDLER
|
||||
if (it.value.lockType === 0 /* LockType.HOLD */)
|
||||
it.value.handler();
|
||||
else
|
||||
it.value.handler(true);
|
||||
return [2 /*return*/];
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Notify, wake all up.
|
||||
*/
|
||||
ConditionVariable.prototype.notify_all = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var resolverList, resolverList_1, resolverList_1_1, resolver;
|
||||
var e_1, _a;
|
||||
return __generator(this, function (_b) {
|
||||
// NOTHING TO NOTIFY
|
||||
if (this.resolvers_.empty())
|
||||
return [2 /*return*/];
|
||||
resolverList = this.resolvers_.toJSON();
|
||||
this.resolvers_.clear();
|
||||
try {
|
||||
// ITERATE RESOLVERS
|
||||
for (resolverList_1 = __values(resolverList), resolverList_1_1 = resolverList_1.next(); !resolverList_1_1.done; resolverList_1_1 = resolverList_1.next()) {
|
||||
resolver = resolverList_1_1.value;
|
||||
if (resolver.lockType === 0 /* LockType.HOLD */)
|
||||
resolver.handler();
|
||||
else
|
||||
resolver.handler(true);
|
||||
}
|
||||
}
|
||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (resolverList_1_1 && !resolverList_1_1.done && (_a = resolverList_1.return)) _a.call(resolverList_1);
|
||||
}
|
||||
finally { if (e_1) throw e_1.error; }
|
||||
}
|
||||
return [2 /*return*/];
|
||||
});
|
||||
});
|
||||
};
|
||||
return ConditionVariable;
|
||||
}());
|
||||
exports.ConditionVariable = ConditionVariable;
|
||||
//# sourceMappingURL=ConditionVariable.js.map
|
||||
-90
@@ -1,90 +0,0 @@
|
||||
/**
|
||||
* Latch for critical sections.
|
||||
*
|
||||
* The `Latch` class blocks critical sections until the downward counter to be zero. Howver,
|
||||
* unlike {@link Barrier} who can reusable that downward counter be reset whenever reach to the
|
||||
* zero, downward of the `Latch` is not reusable but diposable.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class Latch {
|
||||
private cv_;
|
||||
private count_;
|
||||
/**
|
||||
* Initializer Constructor.
|
||||
*
|
||||
* @param size Size of the downward counter.
|
||||
*/
|
||||
constructor(size: number);
|
||||
/**
|
||||
* Waits until the counter to be zero.
|
||||
*
|
||||
* Blocks the function calling until internal counter to be reached to the zero.
|
||||
*
|
||||
* If the {@link Latch} already has been reached to the zero, it would be returned
|
||||
* immediately.
|
||||
*/
|
||||
wait(): Promise<void>;
|
||||
/**
|
||||
* Test whether the counter has been reached to the zero.
|
||||
*
|
||||
* The {@link try_wait} function tests whether the internal counter has been reached to the
|
||||
* zero.
|
||||
*
|
||||
* @return Whether reached to zero or not.
|
||||
*/
|
||||
try_wait(): Promise<boolean>;
|
||||
/**
|
||||
* Tries to wait until the counter to be zero in timeout.
|
||||
*
|
||||
* Attempts to block the function calling until internal counter to be reached to the zero
|
||||
* in timeout. If succeeded to waiting the counter to be reached to the zero, it returns
|
||||
* `true`. Otherwise, the {@link Latch} fails to reach to the zero in the given time, the
|
||||
* function gives up the waiting and returns `false`.
|
||||
*
|
||||
* If the {@link Latch} already has been reached to the zero, it would return `true` directly.
|
||||
*
|
||||
* @param ms The maximum miliseconds for waiting.
|
||||
* @return Whether succeeded to waiting in the given time.
|
||||
*/
|
||||
wait_for(ms: number): Promise<boolean>;
|
||||
/**
|
||||
* Tries to wait until the counter to be zero in time expiration.
|
||||
*
|
||||
* Attempts to block the function calling until internal counter to be reached to the zero
|
||||
* in time expiration. If succeeded to waiting the counter to be reached to the zero, it
|
||||
* returns `true`. Otherwise, the {@link Latch} fails to reach to the zero in the given time,
|
||||
* the function gives up the waiting and returns `false`.
|
||||
*
|
||||
* If the {@link Latch} already has been reached to the zero, it would return `true` directly.
|
||||
*
|
||||
* @param at The maximum time point to wait.
|
||||
* @return Whether succeeded to waiting in the given time.
|
||||
*/
|
||||
wait_until(at: Date): Promise<boolean>;
|
||||
private _Try_wait;
|
||||
/**
|
||||
* Derecements the counter.
|
||||
*
|
||||
* Decrements the counter by *n* without blocking.
|
||||
*
|
||||
* If the parametric value *n* is equal to or greater than internal counter, so that the
|
||||
* internal counter be equal to or less than zero, everyone who are {@link wait waiting} for
|
||||
* the {@link Latch} would continue their execution.
|
||||
*
|
||||
* @param n Value of the decrement. Default is 1.
|
||||
*/
|
||||
count_down(n?: number): Promise<void>;
|
||||
/**
|
||||
* Decrements the counter and waits until the counter to be zero.
|
||||
*
|
||||
* Decrements the counter by *n* and blocks the section until internal counter to be zero.
|
||||
*
|
||||
* If the parametric value *n* is equal to or greater than internal counter, so that the
|
||||
* internal counter be equal to or less than zero, everyone who are {@link wait waiting} for
|
||||
* the {@link Latch} would continue their execution including this one.
|
||||
*
|
||||
* @param n Value of the decrement. Default is 1.
|
||||
*/
|
||||
arrive_and_wait(n?: number): Promise<void>;
|
||||
}
|
||||
-226
@@ -1,226 +0,0 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Latch = void 0;
|
||||
//================================================================
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
//================================================================
|
||||
var ConditionVariable_1 = require("./ConditionVariable");
|
||||
/**
|
||||
* Latch for critical sections.
|
||||
*
|
||||
* The `Latch` class blocks critical sections until the downward counter to be zero. Howver,
|
||||
* unlike {@link Barrier} who can reusable that downward counter be reset whenever reach to the
|
||||
* zero, downward of the `Latch` is not reusable but diposable.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var Latch = /** @class */ (function () {
|
||||
/* ---------------------------------------------------------
|
||||
CONSTRUCTORS
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* Initializer Constructor.
|
||||
*
|
||||
* @param size Size of the downward counter.
|
||||
*/
|
||||
function Latch(size) {
|
||||
this.cv_ = new ConditionVariable_1.ConditionVariable();
|
||||
this.count_ = size;
|
||||
}
|
||||
/* ---------------------------------------------------------
|
||||
WAIT FUNCTIONS
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* Waits until the counter to be zero.
|
||||
*
|
||||
* Blocks the function calling until internal counter to be reached to the zero.
|
||||
*
|
||||
* If the {@link Latch} already has been reached to the zero, it would be returned
|
||||
* immediately.
|
||||
*/
|
||||
Latch.prototype.wait = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
if (!(this._Try_wait() === false)) return [3 /*break*/, 2];
|
||||
return [4 /*yield*/, this.cv_.wait()];
|
||||
case 1:
|
||||
_a.sent();
|
||||
_a.label = 2;
|
||||
case 2: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Test whether the counter has been reached to the zero.
|
||||
*
|
||||
* The {@link try_wait} function tests whether the internal counter has been reached to the
|
||||
* zero.
|
||||
*
|
||||
* @return Whether reached to zero or not.
|
||||
*/
|
||||
Latch.prototype.try_wait = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
return [2 /*return*/, this._Try_wait()];
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Tries to wait until the counter to be zero in timeout.
|
||||
*
|
||||
* Attempts to block the function calling until internal counter to be reached to the zero
|
||||
* in timeout. If succeeded to waiting the counter to be reached to the zero, it returns
|
||||
* `true`. Otherwise, the {@link Latch} fails to reach to the zero in the given time, the
|
||||
* function gives up the waiting and returns `false`.
|
||||
*
|
||||
* If the {@link Latch} already has been reached to the zero, it would return `true` directly.
|
||||
*
|
||||
* @param ms The maximum miliseconds for waiting.
|
||||
* @return Whether succeeded to waiting in the given time.
|
||||
*/
|
||||
Latch.prototype.wait_for = function (ms) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
if (!(this._Try_wait() === true)) return [3 /*break*/, 1];
|
||||
return [2 /*return*/, true];
|
||||
case 1: return [4 /*yield*/, this.cv_.wait_for(ms)];
|
||||
case 2: return [2 /*return*/, _a.sent()];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Tries to wait until the counter to be zero in time expiration.
|
||||
*
|
||||
* Attempts to block the function calling until internal counter to be reached to the zero
|
||||
* in time expiration. If succeeded to waiting the counter to be reached to the zero, it
|
||||
* returns `true`. Otherwise, the {@link Latch} fails to reach to the zero in the given time,
|
||||
* the function gives up the waiting and returns `false`.
|
||||
*
|
||||
* If the {@link Latch} already has been reached to the zero, it would return `true` directly.
|
||||
*
|
||||
* @param at The maximum time point to wait.
|
||||
* @return Whether succeeded to waiting in the given time.
|
||||
*/
|
||||
Latch.prototype.wait_until = function (at) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
if (!(this._Try_wait() === true)) return [3 /*break*/, 1];
|
||||
return [2 /*return*/, true];
|
||||
case 1: return [4 /*yield*/, this.cv_.wait_until(at)];
|
||||
case 2: return [2 /*return*/, _a.sent()];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
Latch.prototype._Try_wait = function () {
|
||||
return this.count_ <= 0;
|
||||
};
|
||||
/* -----------------------------------------------------------
|
||||
ARRIVAL FUNCTIONS
|
||||
----------------------------------------------------------- */
|
||||
/**
|
||||
* Derecements the counter.
|
||||
*
|
||||
* Decrements the counter by *n* without blocking.
|
||||
*
|
||||
* If the parametric value *n* is equal to or greater than internal counter, so that the
|
||||
* internal counter be equal to or less than zero, everyone who are {@link wait waiting} for
|
||||
* the {@link Latch} would continue their execution.
|
||||
*
|
||||
* @param n Value of the decrement. Default is 1.
|
||||
*/
|
||||
Latch.prototype.count_down = function (n) {
|
||||
if (n === void 0) { n = 1; }
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
this.count_ -= n;
|
||||
if (!(this._Try_wait() === true)) return [3 /*break*/, 2];
|
||||
return [4 /*yield*/, this.cv_.notify_all()];
|
||||
case 1:
|
||||
_a.sent();
|
||||
_a.label = 2;
|
||||
case 2: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Decrements the counter and waits until the counter to be zero.
|
||||
*
|
||||
* Decrements the counter by *n* and blocks the section until internal counter to be zero.
|
||||
*
|
||||
* If the parametric value *n* is equal to or greater than internal counter, so that the
|
||||
* internal counter be equal to or less than zero, everyone who are {@link wait waiting} for
|
||||
* the {@link Latch} would continue their execution including this one.
|
||||
*
|
||||
* @param n Value of the decrement. Default is 1.
|
||||
*/
|
||||
Latch.prototype.arrive_and_wait = function (n) {
|
||||
if (n === void 0) { n = 1; }
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, this.count_down(n)];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [4 /*yield*/, this.wait()];
|
||||
case 2:
|
||||
_a.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
return Latch;
|
||||
}());
|
||||
exports.Latch = Latch;
|
||||
//# sourceMappingURL=Latch.js.map
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
/**
|
||||
* Mutable singleton generator.
|
||||
*
|
||||
* The `MutableSingleton` is an asynchronous singleton generator class who guarantees the *lazy
|
||||
* constructor* to be called *"only one at time"*. The *"only one at time"* would always be
|
||||
* kepted, even in the race condition.
|
||||
*
|
||||
* Create a `MutableSingleton` instance with your custom *lazy constructor* and get the promised
|
||||
* value through the {@link MutableSingleton.get}() method. The {@link MutableSingleton.get}()
|
||||
* method would construct the return value following below logics:
|
||||
*
|
||||
* - At the first time: calls the *lazy constructor* and returns the value.
|
||||
* - After the *lazy construction*: returns the pre-constructed value.
|
||||
* - Race condition:
|
||||
* - simultaneously call happens during the *lazy construction*.
|
||||
* - guarantees the *"only one at time"* through a *mutex*.
|
||||
*
|
||||
* If you want to reload the promised value, regardless of whether the *lazy construction* has
|
||||
* been completed or not, call the {@link MutableSingleton.reload}() method. It would call the
|
||||
* *lazy constructor* forcibly, even if the *lany construction* has been completed in sometime.
|
||||
*
|
||||
* @template T Type of the promised value to be lazy-constructed.
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class MutableSingleton<T, Args extends any[] = []> {
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
private readonly closure_;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
private readonly mutex_;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
private value_;
|
||||
/**
|
||||
* Initializer Constructor.
|
||||
*
|
||||
* Create a new `Singleton` instance with the *lazy consturctor*.
|
||||
*
|
||||
* @param closure Lazy constructor function returning the promised value.
|
||||
*/
|
||||
constructor(closure: (...args: Args) => Promise<T>);
|
||||
/**
|
||||
* Reload value.
|
||||
*
|
||||
* The `MutableSingleton.reload()` method enforces to call the *lazy constructor*, regardless
|
||||
* of whether the *lazy construction* has been completed or not. Therefore, even if the *lazy
|
||||
* construction* has been completed in sometime, the `MutableSingleton.reload()` will call
|
||||
* the *lazy constructor* again.
|
||||
*
|
||||
* @return Re-constructed value.
|
||||
*/
|
||||
reload(...args: Args): Promise<T>;
|
||||
/**
|
||||
* Configure value.
|
||||
*
|
||||
* The `MutableSingleton.set()` method enforces the singleton to have a specific value.
|
||||
*
|
||||
* @param value The value to configure
|
||||
*/
|
||||
set(value: T): Promise<void>;
|
||||
/**
|
||||
* Clear value.
|
||||
*
|
||||
* The `MutableSingleton.clear()` is a method clearing cached value.
|
||||
*
|
||||
* Therefore, when {@link get} being called, closure of constructor would be reused.
|
||||
*/
|
||||
clear(): Promise<void>;
|
||||
/**
|
||||
* Get promised value.
|
||||
*
|
||||
* `MutableSingleton.get()` method returns the *lazy constructed value*. It guarantees the
|
||||
* *lazy constructor* to be called *"only one at time"*. It ensures the *"only one at time"*,
|
||||
* even in the race condition.
|
||||
*
|
||||
* If the promised value is not constructed yet (call this method at the first time), the
|
||||
* *lazy constructor* would be called and returns the promised value. Otherwise, the promised
|
||||
* value has been already constructed by the *lazy constructor* (this method already had been
|
||||
* called), returns the pre-generated value.
|
||||
*
|
||||
* Also, you don't need to worry anything about the race condition, who may be occured by
|
||||
* calling the `MutableSingleton.get()` method simultaneously during the *lazy construction*
|
||||
* is on going. The `MutableSingleton` guarantees the *lazy constructor* to be called
|
||||
* only one at time by using the {@link UniqueLock.lock} on a {@link Mutex}.
|
||||
*
|
||||
* @return The *lazy constructed* value.
|
||||
*/
|
||||
get(...args: Args): Promise<T>;
|
||||
/**
|
||||
* Test whether the value has been loaded.
|
||||
*
|
||||
* The `MutableSingleton.is_loaded()` method tests whether the singleton has coompleted to
|
||||
* constructing its value or not. If the singleton value is on the construction by the
|
||||
* {@link MutableSingleton.get} or {@link MutableSingleton.reload} method, the
|
||||
* `MutableSingleton.is_loaded()` would wait returning value until the construction has been
|
||||
* completed.
|
||||
*
|
||||
* @returns Whether loaded or not
|
||||
*/
|
||||
is_loaded(): Promise<boolean>;
|
||||
}
|
||||
-304
@@ -1,304 +0,0 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var __read = (this && this.__read) || function (o, n) {
|
||||
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
||||
if (!m) return o;
|
||||
var i = m.call(o), r, ar = [], e;
|
||||
try {
|
||||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
||||
}
|
||||
catch (error) { e = { error: error }; }
|
||||
finally {
|
||||
try {
|
||||
if (r && !r.done && (m = i["return"])) m.call(i);
|
||||
}
|
||||
finally { if (e) throw e.error; }
|
||||
}
|
||||
return ar;
|
||||
};
|
||||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
||||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
||||
if (ar || !(i in from)) {
|
||||
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
||||
ar[i] = from[i];
|
||||
}
|
||||
}
|
||||
return to.concat(ar || Array.prototype.slice.call(from));
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.MutableSingleton = void 0;
|
||||
//================================================================
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
//================================================================
|
||||
var SharedMutex_1 = require("./SharedMutex");
|
||||
var SharedLock_1 = require("./SharedLock");
|
||||
var UniqueLock_1 = require("./UniqueLock");
|
||||
/**
|
||||
* Mutable singleton generator.
|
||||
*
|
||||
* The `MutableSingleton` is an asynchronous singleton generator class who guarantees the *lazy
|
||||
* constructor* to be called *"only one at time"*. The *"only one at time"* would always be
|
||||
* kepted, even in the race condition.
|
||||
*
|
||||
* Create a `MutableSingleton` instance with your custom *lazy constructor* and get the promised
|
||||
* value through the {@link MutableSingleton.get}() method. The {@link MutableSingleton.get}()
|
||||
* method would construct the return value following below logics:
|
||||
*
|
||||
* - At the first time: calls the *lazy constructor* and returns the value.
|
||||
* - After the *lazy construction*: returns the pre-constructed value.
|
||||
* - Race condition:
|
||||
* - simultaneously call happens during the *lazy construction*.
|
||||
* - guarantees the *"only one at time"* through a *mutex*.
|
||||
*
|
||||
* If you want to reload the promised value, regardless of whether the *lazy construction* has
|
||||
* been completed or not, call the {@link MutableSingleton.reload}() method. It would call the
|
||||
* *lazy constructor* forcibly, even if the *lany construction* has been completed in sometime.
|
||||
*
|
||||
* @template T Type of the promised value to be lazy-constructed.
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var MutableSingleton = /** @class */ (function () {
|
||||
/* ---------------------------------------------------------------
|
||||
CONSTRUCTORS
|
||||
--------------------------------------------------------------- */
|
||||
/**
|
||||
* Initializer Constructor.
|
||||
*
|
||||
* Create a new `Singleton` instance with the *lazy consturctor*.
|
||||
*
|
||||
* @param closure Lazy constructor function returning the promised value.
|
||||
*/
|
||||
function MutableSingleton(closure) {
|
||||
this.closure_ = closure;
|
||||
this.mutex_ = new SharedMutex_1.SharedMutex();
|
||||
this.value_ = NOT_MOUNTED_YET;
|
||||
}
|
||||
/**
|
||||
* Reload value.
|
||||
*
|
||||
* The `MutableSingleton.reload()` method enforces to call the *lazy constructor*, regardless
|
||||
* of whether the *lazy construction* has been completed or not. Therefore, even if the *lazy
|
||||
* construction* has been completed in sometime, the `MutableSingleton.reload()` will call
|
||||
* the *lazy constructor* again.
|
||||
*
|
||||
* @return Re-constructed value.
|
||||
*/
|
||||
MutableSingleton.prototype.reload = function () {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var output;
|
||||
var _this = this;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, UniqueLock_1.UniqueLock.lock(this.mutex_, function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, this.closure_.apply(this, __spreadArray([], __read(args), false))];
|
||||
case 1:
|
||||
output = _a.sent();
|
||||
this.value_ = output;
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); })];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [2 /*return*/, output];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Configure value.
|
||||
*
|
||||
* The `MutableSingleton.set()` method enforces the singleton to have a specific value.
|
||||
*
|
||||
* @param value The value to configure
|
||||
*/
|
||||
MutableSingleton.prototype.set = function (value) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var _this = this;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, UniqueLock_1.UniqueLock.lock(this.mutex_, function () {
|
||||
_this.value_ = value;
|
||||
})];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Clear value.
|
||||
*
|
||||
* The `MutableSingleton.clear()` is a method clearing cached value.
|
||||
*
|
||||
* Therefore, when {@link get} being called, closure of constructor would be reused.
|
||||
*/
|
||||
MutableSingleton.prototype.clear = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var _this = this;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, UniqueLock_1.UniqueLock.lock(this.mutex_, function () {
|
||||
_this.value_ = NOT_MOUNTED_YET;
|
||||
})];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/* ---------------------------------------------------------------
|
||||
ACCESSORS
|
||||
--------------------------------------------------------------- */
|
||||
/**
|
||||
* Get promised value.
|
||||
*
|
||||
* `MutableSingleton.get()` method returns the *lazy constructed value*. It guarantees the
|
||||
* *lazy constructor* to be called *"only one at time"*. It ensures the *"only one at time"*,
|
||||
* even in the race condition.
|
||||
*
|
||||
* If the promised value is not constructed yet (call this method at the first time), the
|
||||
* *lazy constructor* would be called and returns the promised value. Otherwise, the promised
|
||||
* value has been already constructed by the *lazy constructor* (this method already had been
|
||||
* called), returns the pre-generated value.
|
||||
*
|
||||
* Also, you don't need to worry anything about the race condition, who may be occured by
|
||||
* calling the `MutableSingleton.get()` method simultaneously during the *lazy construction*
|
||||
* is on going. The `MutableSingleton` guarantees the *lazy constructor* to be called
|
||||
* only one at time by using the {@link UniqueLock.lock} on a {@link Mutex}.
|
||||
*
|
||||
* @return The *lazy constructed* value.
|
||||
*/
|
||||
MutableSingleton.prototype.get = function () {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var output;
|
||||
var _this = this;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
output = NOT_MOUNTED_YET;
|
||||
return [4 /*yield*/, SharedLock_1.SharedLock.lock(this.mutex_, function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
output = this.value_;
|
||||
return [2 /*return*/];
|
||||
});
|
||||
}); })];
|
||||
case 1:
|
||||
_a.sent();
|
||||
if (!(output === NOT_MOUNTED_YET)) return [3 /*break*/, 3];
|
||||
return [4 /*yield*/, UniqueLock_1.UniqueLock.lock(this.mutex_, function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
// COULD BE COMPLETED DURING WAITING
|
||||
if (this.value_ !== NOT_MOUNTED_YET) {
|
||||
output = this.value_;
|
||||
return [2 /*return*/];
|
||||
}
|
||||
return [4 /*yield*/, this.closure_.apply(this, __spreadArray([], __read(args), false))];
|
||||
case 1:
|
||||
// CALL THE LAZY-CONSTRUCTOR
|
||||
output = _a.sent();
|
||||
this.value_ = output;
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); })];
|
||||
case 2:
|
||||
_a.sent();
|
||||
_a.label = 3;
|
||||
case 3: return [2 /*return*/, output];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Test whether the value has been loaded.
|
||||
*
|
||||
* The `MutableSingleton.is_loaded()` method tests whether the singleton has coompleted to
|
||||
* constructing its value or not. If the singleton value is on the construction by the
|
||||
* {@link MutableSingleton.get} or {@link MutableSingleton.reload} method, the
|
||||
* `MutableSingleton.is_loaded()` would wait returning value until the construction has been
|
||||
* completed.
|
||||
*
|
||||
* @returns Whether loaded or not
|
||||
*/
|
||||
MutableSingleton.prototype.is_loaded = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var loaded;
|
||||
var _this = this;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
loaded = false;
|
||||
return [4 /*yield*/, SharedLock_1.SharedLock.lock(this.mutex_, function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
loaded = this.value_ !== NOT_MOUNTED_YET;
|
||||
return [2 /*return*/];
|
||||
});
|
||||
}); })];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [2 /*return*/, loaded];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
return MutableSingleton;
|
||||
}());
|
||||
exports.MutableSingleton = MutableSingleton;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
var NOT_MOUNTED_YET = {};
|
||||
//# sourceMappingURL=MutableSingleton.js.map
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
import { ILockable } from "../base/thread/ILockable";
|
||||
/**
|
||||
* Mutex.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class Mutex implements ILockable {
|
||||
private mutex_;
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
constructor();
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
lock(): Promise<void>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
try_lock(): Promise<boolean>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
unlock(): Promise<void>;
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Mutex = void 0;
|
||||
var SharedTimedMutex_1 = require("./SharedTimedMutex");
|
||||
/**
|
||||
* Mutex.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var Mutex = /** @class */ (function () {
|
||||
/* ---------------------------------------------------------
|
||||
CONSTRUCTOR
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
function Mutex() {
|
||||
this.mutex_ = new SharedTimedMutex_1.SharedTimedMutex(this);
|
||||
}
|
||||
/* ---------------------------------------------------------
|
||||
LOCK & UNLOCK
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
Mutex.prototype.lock = function () {
|
||||
return this.mutex_.lock();
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
Mutex.prototype.try_lock = function () {
|
||||
return this.mutex_.try_lock();
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
Mutex.prototype.unlock = function () {
|
||||
return this.mutex_.unlock();
|
||||
};
|
||||
return Mutex;
|
||||
}());
|
||||
exports.Mutex = Mutex;
|
||||
//# sourceMappingURL=Mutex.js.map
|
||||
-138
@@ -1,138 +0,0 @@
|
||||
import { ITimedLockable } from "../base/thread/ITimedLockable";
|
||||
/**
|
||||
* Counting semaphore.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class Semaphore<Max extends number = number> {
|
||||
private queue_;
|
||||
private acquiring_;
|
||||
private max_;
|
||||
/**
|
||||
* Initializer Constructor.
|
||||
*
|
||||
* @param max Number of maximum sections acquirable.
|
||||
*/
|
||||
constructor(max: Max);
|
||||
/**
|
||||
* Get number of maximum sections lockable.
|
||||
*
|
||||
* @return Number of maximum sections lockable.
|
||||
*/
|
||||
max(): Max;
|
||||
/**
|
||||
* Acquires a section.
|
||||
*
|
||||
* Acquires a section until be {@link release released}. If all of the sections in the
|
||||
* semaphore already have been acquired by others, the function call would be blocked until
|
||||
* one of them returns its acquisition by calling the {@link release} method.
|
||||
*
|
||||
* In same reason, if you don't call the {@link release} function after you business, the
|
||||
* others who want to {@link acquire} a section from the semaphore would be fall into the
|
||||
* forever sleep. Therefore, never forget to calling the {@link release} function or utilize
|
||||
* the {@link UniqueLock.lock} function instead with {@link Semaphore.get_lockable} to ensure
|
||||
* the safety.
|
||||
*/
|
||||
acquire(): Promise<void>;
|
||||
/**
|
||||
* Tries to acquire a section.
|
||||
*
|
||||
* Attempts to acquire a section without blocking. If succeeded to acquire a section from the
|
||||
* semaphore immediately, it returns `true` directly. Otherwise all of the sections in the
|
||||
* semaphore are full, the function gives up the trial immediately and returns `false`
|
||||
* directly.
|
||||
*
|
||||
* Note that, if you succeeded to acquire a section from the semaphore (returns `true) but do
|
||||
* not call the {@link release} function after your business, the others who want to
|
||||
* {@link acquire} a section from the semaphore would be fall into the forever sleep.
|
||||
* Therefore, never forget to calling the {@link release} function or utilize the
|
||||
* {@link UniqueLock.try_lock} function instead with {@link Semaphore.get_lockable} to ensure
|
||||
* the safety.
|
||||
*
|
||||
* @return Whether succeeded to acquire or not.
|
||||
*/
|
||||
try_acquire(): Promise<boolean>;
|
||||
/**
|
||||
* Tries to acquire a section until timeout.
|
||||
*
|
||||
* Attempts to acquire a section from the semaphore until timeout. If succeeded to acquire a
|
||||
* section until the timeout, it returns `true`. Otherwise failed to acquiring a section in
|
||||
* given the time, the function gives up the trial and returns `false`.
|
||||
*
|
||||
* Failed to acquiring a section in the given time (returns `false`), it means that there're
|
||||
* someone who have already {@link acquire acquired} sections and do not return them over the
|
||||
* time expiration.
|
||||
*
|
||||
* Note that, if you succeeded to acquire a section from the semaphore (returns `true) but do
|
||||
* not call the {@link release} function after your business, the others who want to
|
||||
* {@link acquire} a section from the semaphore would be fall into the forever sleep.
|
||||
* Therefore, never forget to calling the {@link release} function or utilize the
|
||||
* {@link UniqueLock.try_acquire_for} function instead with {@link Semaphore.get_lockable} to
|
||||
* ensure the safety.
|
||||
*
|
||||
* @param ms The maximum miliseconds for waiting.
|
||||
* @return Whether succeded to acquire or not.
|
||||
*/
|
||||
try_acquire_for(ms: number): Promise<boolean>;
|
||||
/**
|
||||
* Tries to acquire a section until timeout.
|
||||
*
|
||||
* Attempts to acquire a section from the semaphore until time expiration. If succeeded to
|
||||
* acquire a section until the time expiration, it returns `true`. Otherwise failed to
|
||||
* acquiring a section in the given time, the function gives up the trial and returns `false`.
|
||||
*
|
||||
* Failed to acquiring a section in the given time (returns `false`), it means that there're
|
||||
* someone who have already {@link acquire acquired} sections and do not return them over the
|
||||
* time expiration.
|
||||
*
|
||||
* Note that, if you succeeded to acquire a section from the semaphore (returns `true) but do
|
||||
* not call the {@link release} function after your business, the others who want to
|
||||
* {@link acquire} a section from the semaphore would be fall into the forever sleep.
|
||||
* Therefore, never forget to calling the {@link release} function or utilize the
|
||||
* {@link UniqueLock.try_acquire_until} function instead with {@link Semaphore.get_lockable}
|
||||
* to ensure the safety.
|
||||
*
|
||||
* @param at The maximum time point to wait.
|
||||
* @return Whether succeded to acquire or not.
|
||||
*/
|
||||
try_acquire_until(at: Date): Promise<boolean>;
|
||||
/**
|
||||
* Release sections.
|
||||
*
|
||||
* When you call this {@link release} method and there're someone who are currently blocked
|
||||
* by attemping to {@link acquire} a section from this semaphore, *n* of them
|
||||
* (FIFO; first-in-first-out) would {@link acquire} those {@link release released} sections
|
||||
* and continue their executions.
|
||||
*
|
||||
* Otherwise, there's not anyone who is {@link acquire acquiring} the section or number of
|
||||
* the blocked are less than *n*, the {@link OutOfRange} error would be thrown.
|
||||
*
|
||||
* > As you know, when you succeeded to {@link acquire} a section, you don't have to forget
|
||||
* > to calling this {@link release} method after your business. If you forget it, it would
|
||||
* > be a terrible situation for the others who're attempting to {@link acquire} a section
|
||||
* > from this semaphore.
|
||||
* >
|
||||
* > However, if you utilize the {@link UniqueLock} with {@link Semaphore.get_lockable}, you
|
||||
* > don't need to consider about this {@link release} method. Just define your business into
|
||||
* > a callback function as a parameter of methods of the {@link UniqueLock}, then this
|
||||
* > {@link release} method would be automatically called by the {@link UniqueLock} after the
|
||||
* > business.
|
||||
*
|
||||
* @param n Number of sections to be released. Default is 1.
|
||||
* @throw {@link OutOfRange} when *n* is greater than currently {@link acquire acquired} sections.
|
||||
*/
|
||||
release(n?: number): Promise<void>;
|
||||
private _Cancel;
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export declare namespace Semaphore {
|
||||
/**
|
||||
* Capsules a {@link Semaphore} to be suitable for the {@link UniqueLock}.
|
||||
*
|
||||
* @param semaphore Target semaphore to capsule.
|
||||
* @return Lockable instance suitable for the {@link UniqueLock}
|
||||
*/
|
||||
function get_lockable<SemaphoreT extends Pick<Semaphore, "acquire" | "try_acquire" | "try_acquire_for" | "try_acquire_until" | "release">>(semaphore: SemaphoreT): ITimedLockable;
|
||||
}
|
||||
-363
@@ -1,363 +0,0 @@
|
||||
"use strict";
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var __values = (this && this.__values) || function(o) {
|
||||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
||||
if (m) return m.call(o);
|
||||
if (o && typeof o.length === "number") return {
|
||||
next: function () {
|
||||
if (o && i >= o.length) o = void 0;
|
||||
return { value: o && o[i++], done: !o };
|
||||
}
|
||||
};
|
||||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Semaphore = void 0;
|
||||
//================================================================
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
//================================================================
|
||||
var List_1 = require("../container/List");
|
||||
var InvalidArgument_1 = require("../exception/InvalidArgument");
|
||||
var OutOfRange_1 = require("../exception/OutOfRange");
|
||||
var global_1 = require("./global");
|
||||
/**
|
||||
* Counting semaphore.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var Semaphore = /** @class */ (function () {
|
||||
/* ---------------------------------------------------------
|
||||
CONSTRUCTORS
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* Initializer Constructor.
|
||||
*
|
||||
* @param max Number of maximum sections acquirable.
|
||||
*/
|
||||
function Semaphore(max) {
|
||||
this.queue_ = new List_1.List();
|
||||
this.acquiring_ = 0;
|
||||
this.max_ = max;
|
||||
}
|
||||
/**
|
||||
* Get number of maximum sections lockable.
|
||||
*
|
||||
* @return Number of maximum sections lockable.
|
||||
*/
|
||||
Semaphore.prototype.max = function () {
|
||||
return this.max_;
|
||||
};
|
||||
/* ---------------------------------------------------------
|
||||
ACQUIRANCES
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* Acquires a section.
|
||||
*
|
||||
* Acquires a section until be {@link release released}. If all of the sections in the
|
||||
* semaphore already have been acquired by others, the function call would be blocked until
|
||||
* one of them returns its acquisition by calling the {@link release} method.
|
||||
*
|
||||
* In same reason, if you don't call the {@link release} function after you business, the
|
||||
* others who want to {@link acquire} a section from the semaphore would be fall into the
|
||||
* forever sleep. Therefore, never forget to calling the {@link release} function or utilize
|
||||
* the {@link UniqueLock.lock} function instead with {@link Semaphore.get_lockable} to ensure
|
||||
* the safety.
|
||||
*/
|
||||
Semaphore.prototype.acquire = function () {
|
||||
var _this = this;
|
||||
return new Promise(function (resolve) {
|
||||
if (_this.acquiring_ < _this.max_) {
|
||||
++_this.acquiring_;
|
||||
resolve();
|
||||
}
|
||||
else {
|
||||
_this.queue_.push_back({
|
||||
handler: resolve,
|
||||
lockType: 0 /* LockType.HOLD */,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Tries to acquire a section.
|
||||
*
|
||||
* Attempts to acquire a section without blocking. If succeeded to acquire a section from the
|
||||
* semaphore immediately, it returns `true` directly. Otherwise all of the sections in the
|
||||
* semaphore are full, the function gives up the trial immediately and returns `false`
|
||||
* directly.
|
||||
*
|
||||
* Note that, if you succeeded to acquire a section from the semaphore (returns `true) but do
|
||||
* not call the {@link release} function after your business, the others who want to
|
||||
* {@link acquire} a section from the semaphore would be fall into the forever sleep.
|
||||
* Therefore, never forget to calling the {@link release} function or utilize the
|
||||
* {@link UniqueLock.try_lock} function instead with {@link Semaphore.get_lockable} to ensure
|
||||
* the safety.
|
||||
*
|
||||
* @return Whether succeeded to acquire or not.
|
||||
*/
|
||||
Semaphore.prototype.try_acquire = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
// ALL OR NOTHING
|
||||
if (this.acquiring_ < this.max_) {
|
||||
++this.acquiring_;
|
||||
return [2 /*return*/, true];
|
||||
}
|
||||
else
|
||||
return [2 /*return*/, false];
|
||||
return [2 /*return*/];
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Tries to acquire a section until timeout.
|
||||
*
|
||||
* Attempts to acquire a section from the semaphore until timeout. If succeeded to acquire a
|
||||
* section until the timeout, it returns `true`. Otherwise failed to acquiring a section in
|
||||
* given the time, the function gives up the trial and returns `false`.
|
||||
*
|
||||
* Failed to acquiring a section in the given time (returns `false`), it means that there're
|
||||
* someone who have already {@link acquire acquired} sections and do not return them over the
|
||||
* time expiration.
|
||||
*
|
||||
* Note that, if you succeeded to acquire a section from the semaphore (returns `true) but do
|
||||
* not call the {@link release} function after your business, the others who want to
|
||||
* {@link acquire} a section from the semaphore would be fall into the forever sleep.
|
||||
* Therefore, never forget to calling the {@link release} function or utilize the
|
||||
* {@link UniqueLock.try_acquire_for} function instead with {@link Semaphore.get_lockable} to
|
||||
* ensure the safety.
|
||||
*
|
||||
* @param ms The maximum miliseconds for waiting.
|
||||
* @return Whether succeded to acquire or not.
|
||||
*/
|
||||
Semaphore.prototype.try_acquire_for = function (ms) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var _this = this;
|
||||
return __generator(this, function (_a) {
|
||||
return [2 /*return*/, new Promise(function (resolve) {
|
||||
if (_this.acquiring_ < _this.max_) {
|
||||
++_this.acquiring_;
|
||||
resolve(true);
|
||||
}
|
||||
else {
|
||||
// RESERVE ACQUIRE
|
||||
var it_1 = _this.queue_.insert(_this.queue_.end(), {
|
||||
handler: resolve,
|
||||
lockType: 1 /* LockType.KNOCK */,
|
||||
});
|
||||
// AUTOMATIC RELEASE AFTER TIMEOUT
|
||||
(0, global_1.sleep_for)(ms).then(function () {
|
||||
// NOT YET, THEN DO RELEASE
|
||||
if (it_1.value.handler !== null)
|
||||
_this._Cancel(it_1);
|
||||
});
|
||||
}
|
||||
})];
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Tries to acquire a section until timeout.
|
||||
*
|
||||
* Attempts to acquire a section from the semaphore until time expiration. If succeeded to
|
||||
* acquire a section until the time expiration, it returns `true`. Otherwise failed to
|
||||
* acquiring a section in the given time, the function gives up the trial and returns `false`.
|
||||
*
|
||||
* Failed to acquiring a section in the given time (returns `false`), it means that there're
|
||||
* someone who have already {@link acquire acquired} sections and do not return them over the
|
||||
* time expiration.
|
||||
*
|
||||
* Note that, if you succeeded to acquire a section from the semaphore (returns `true) but do
|
||||
* not call the {@link release} function after your business, the others who want to
|
||||
* {@link acquire} a section from the semaphore would be fall into the forever sleep.
|
||||
* Therefore, never forget to calling the {@link release} function or utilize the
|
||||
* {@link UniqueLock.try_acquire_until} function instead with {@link Semaphore.get_lockable}
|
||||
* to ensure the safety.
|
||||
*
|
||||
* @param at The maximum time point to wait.
|
||||
* @return Whether succeded to acquire or not.
|
||||
*/
|
||||
Semaphore.prototype.try_acquire_until = function (at) {
|
||||
// COMPUTE MILLISECONDS TO WAIT
|
||||
var now = new Date();
|
||||
var ms = at.getTime() - now.getTime();
|
||||
return this.try_acquire_for(ms);
|
||||
};
|
||||
/* ---------------------------------------------------------
|
||||
RELEASES
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* Release sections.
|
||||
*
|
||||
* When you call this {@link release} method and there're someone who are currently blocked
|
||||
* by attemping to {@link acquire} a section from this semaphore, *n* of them
|
||||
* (FIFO; first-in-first-out) would {@link acquire} those {@link release released} sections
|
||||
* and continue their executions.
|
||||
*
|
||||
* Otherwise, there's not anyone who is {@link acquire acquiring} the section or number of
|
||||
* the blocked are less than *n*, the {@link OutOfRange} error would be thrown.
|
||||
*
|
||||
* > As you know, when you succeeded to {@link acquire} a section, you don't have to forget
|
||||
* > to calling this {@link release} method after your business. If you forget it, it would
|
||||
* > be a terrible situation for the others who're attempting to {@link acquire} a section
|
||||
* > from this semaphore.
|
||||
* >
|
||||
* > However, if you utilize the {@link UniqueLock} with {@link Semaphore.get_lockable}, you
|
||||
* > don't need to consider about this {@link release} method. Just define your business into
|
||||
* > a callback function as a parameter of methods of the {@link UniqueLock}, then this
|
||||
* > {@link release} method would be automatically called by the {@link UniqueLock} after the
|
||||
* > business.
|
||||
*
|
||||
* @param n Number of sections to be released. Default is 1.
|
||||
* @throw {@link OutOfRange} when *n* is greater than currently {@link acquire acquired} sections.
|
||||
*/
|
||||
Semaphore.prototype.release = function (n) {
|
||||
if (n === void 0) { n = 1; }
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var resolverList, resolver, resolverList_1, resolverList_1_1, resolver;
|
||||
var e_1, _a;
|
||||
return __generator(this, function (_b) {
|
||||
//----
|
||||
// VALIDATION
|
||||
//----
|
||||
if (n < 1)
|
||||
throw new InvalidArgument_1.InvalidArgument("Error on std.Semaphore.release(): parametric n is less than 1 -> (n = ".concat(n, ")."));
|
||||
else if (n > this.max_)
|
||||
throw new OutOfRange_1.OutOfRange("Error on std.Semaphore.release(): parametric n is greater than max -> (n = ".concat(n, ", max = ").concat(this.max_, ")."));
|
||||
else if (n > this.acquiring_)
|
||||
throw new OutOfRange_1.OutOfRange("Error on std.Semaphore.release(): parametric n is greater than acquiring -> (n = ".concat(n, ", acquiring = ").concat(this.acquiring_, ")."));
|
||||
resolverList = [];
|
||||
while (this.queue_.empty() === false && resolverList.length < n) {
|
||||
resolver = this.queue_.front();
|
||||
if (resolver.handler !== null)
|
||||
resolverList.push(__assign({}, resolver));
|
||||
// DESTRUCT
|
||||
this.queue_.pop_front();
|
||||
resolver.handler = null;
|
||||
}
|
||||
// COMPUTE REMAINED ACQUIRANCES
|
||||
this.acquiring_ -= n - resolverList.length;
|
||||
try {
|
||||
// CALL HANDLERS
|
||||
for (resolverList_1 = __values(resolverList), resolverList_1_1 = resolverList_1.next(); !resolverList_1_1.done; resolverList_1_1 = resolverList_1.next()) {
|
||||
resolver = resolverList_1_1.value;
|
||||
if (resolver.lockType === 0 /* LockType.HOLD */)
|
||||
resolver.handler();
|
||||
else
|
||||
resolver.handler(true);
|
||||
}
|
||||
}
|
||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (resolverList_1_1 && !resolverList_1_1.done && (_a = resolverList_1.return)) _a.call(resolverList_1);
|
||||
}
|
||||
finally { if (e_1) throw e_1.error; }
|
||||
}
|
||||
return [2 /*return*/];
|
||||
});
|
||||
});
|
||||
};
|
||||
Semaphore.prototype._Cancel = function (it) {
|
||||
// POP THE LISTENER
|
||||
var handler = it.value.handler;
|
||||
// DESTRUCTION
|
||||
it.value.handler = null;
|
||||
this.queue_.erase(it);
|
||||
// RETURNS FAILURE
|
||||
handler(false);
|
||||
};
|
||||
return Semaphore;
|
||||
}());
|
||||
exports.Semaphore = Semaphore;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
(function (Semaphore) {
|
||||
/**
|
||||
* Capsules a {@link Semaphore} to be suitable for the {@link UniqueLock}.
|
||||
*
|
||||
* @param semaphore Target semaphore to capsule.
|
||||
* @return Lockable instance suitable for the {@link UniqueLock}
|
||||
*/
|
||||
function get_lockable(semaphore) {
|
||||
return new Lockable(semaphore);
|
||||
}
|
||||
Semaphore.get_lockable = get_lockable;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
var Lockable = /** @class */ (function () {
|
||||
function Lockable(semaphore) {
|
||||
this.semahpore_ = semaphore;
|
||||
}
|
||||
Lockable.prototype.lock = function () {
|
||||
return this.semahpore_.acquire();
|
||||
};
|
||||
Lockable.prototype.unlock = function () {
|
||||
return this.semahpore_.release();
|
||||
};
|
||||
Lockable.prototype.try_lock = function () {
|
||||
return this.semahpore_.try_acquire();
|
||||
};
|
||||
Lockable.prototype.try_lock_for = function (ms) {
|
||||
return this.semahpore_.try_acquire_for(ms);
|
||||
};
|
||||
Lockable.prototype.try_lock_until = function (at) {
|
||||
return this.semahpore_.try_acquire_until(at);
|
||||
};
|
||||
return Lockable;
|
||||
}());
|
||||
Semaphore.Lockable = Lockable;
|
||||
})(Semaphore = exports.Semaphore || (exports.Semaphore = {}));
|
||||
exports.Semaphore = Semaphore;
|
||||
//# sourceMappingURL=Semaphore.js.map
|
||||
-136
@@ -1,136 +0,0 @@
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
import { ISharedLockable } from "../base/thread/ISharedLockable";
|
||||
import { ISharedTimedLockable } from "../base/thread/ISharedTimedLockable";
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export declare class SharedLock {
|
||||
}
|
||||
/**
|
||||
* Shared mutex wrapper for the safe read lock.
|
||||
*
|
||||
* The module {@link SharedLock} is a collection of general purpose functions wrapping shared
|
||||
* mutex for ensuring the safe lock. If you *lock* a mutex (with your business logic code) through
|
||||
* any function of the {@link SharedLock} module, the shared mutex would be automatically
|
||||
* *unlocked* after your business, even if an error has been occured in your business.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare namespace SharedLock {
|
||||
/**
|
||||
* Read locks a shared mutex with your business.
|
||||
*
|
||||
* Shares a mutex until be the *closure* has been completed. If there're someone who have
|
||||
* already {@link ILockable.lock monopolied} the mutex, the function call would be blocked
|
||||
* until all of them to {@link unlock return} their acquisitions.
|
||||
*
|
||||
* When succeeded to {@link ISharedLockable.lock_shared share} the mutex, the {@link lock}
|
||||
* function will call the *closure*, a custom function defning your business. After the
|
||||
* *closure* function be returned, the {@link lock} function automatically
|
||||
* {@link ISharedLockable.unlock_shared unlocks} the mutex, even if the *closure* function
|
||||
* throws any error.
|
||||
*
|
||||
* Therefore, when using this {@link lock} function, you don't need to consider about
|
||||
* {@link ISharedLockable.unlock_shared returning} the lock acquistion after your business.
|
||||
* It would just be done automatically.
|
||||
*
|
||||
* @param mutex Target shared mutex to read lock.
|
||||
* @param closure A function defining your business.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
export function lock<Mutex extends Pick<ISharedLockable, "lock_shared" | "unlock_shared">>(mutex: Mutex, closure: Closure): Promise<void>;
|
||||
/**
|
||||
* Tries to read lock a shared mutex with your business.
|
||||
*
|
||||
* Attemps to share a mutex without blocking. If succeeded to share the mutex immediately, it
|
||||
* returns `true` directly. Otherwise there's someone who has already
|
||||
* {@link ILockable.lock monopolied} the mutex, the function gives up the trial immediately
|
||||
* and returns `false` directly without calling the *closure*.
|
||||
*
|
||||
* When succeeded to {@link ISharedLockable.lock_shared share} the mutex, the {@link try_lock}
|
||||
* function will call the *closure*, a custom function defning your business. After the
|
||||
* *closure* function be returned, the {@link try_lock} function automatically
|
||||
* {@link ISharedLockable.unlock_shared unlocks} the mutex, even if the *closure* function
|
||||
* throws any error.
|
||||
*
|
||||
* Therefore, when using this {@link try_lock} function, you don't need to consider about
|
||||
* {@link ISharedLockable.unlock_shared returning} the lock acquistion after your business.
|
||||
* It would just be done automatically.
|
||||
*
|
||||
* @param mutex Target shared mutex to try read lock.
|
||||
* @param closure A function defining your business.
|
||||
* @return Whether succeeded to share the mutex or not.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
export function try_lock<Mutex extends Pick<ISharedLockable, "try_lock_shared" | "unlock_shared">>(mutex: Mutex, closure: Closure): Promise<boolean>;
|
||||
/**
|
||||
* Tries to read lock a shared mutex with your business until timeout.
|
||||
*
|
||||
* Attemps to share a mutex until timeout. If succeeded to share the mutex until timeout, it
|
||||
* returns `true` after calling the *closure*. Otherwise failed to acquiring the shared lock
|
||||
* in the given time, the function gives up the trial and returns `false` without calling the
|
||||
* *closure*.
|
||||
*
|
||||
* Failed to acquring the shared lock in the given time (returns `false`), it means that
|
||||
* there's someone who has already {@link ILockable.lock monopolied} the mutex and does not
|
||||
* return it over the timeout.
|
||||
*
|
||||
* When succeeded to {@link ISharedLockable.lock_shared share} the mutex, the
|
||||
* {@link try_lock_for} function will call the *closure*, a custom function defning your
|
||||
* business. After the *closure* function be returned, the {@link try_lock} function
|
||||
* automatically {@link ISharedLockable.unlock_shared unlocks} the mutex, even if the
|
||||
* *closure* function throws any error.
|
||||
*
|
||||
* Therefore, when using this {@link try_lock_for} function, you don't need to consider about
|
||||
* {@link ISharedLockable.unlock_shared returning} the lock acquistion after your business.
|
||||
* It would just be done automatically.
|
||||
*
|
||||
* @param mutex Target mutex to try lock until timeout.
|
||||
* @param ms The maximum miliseconds for waiting.
|
||||
* @param closure A function defining your business.
|
||||
* @return Whether succeeded to share the mutex or not.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
export function try_lock_for<Mutex extends Pick<ISharedTimedLockable, "try_lock_shared_for" | "unlock_shared">>(mutex: Mutex, ms: number, closure: Closure): Promise<boolean>;
|
||||
/**
|
||||
* Tries to read lock a shared mutex with your business until time expiration.
|
||||
*
|
||||
* Attemps to share a mutex until time expiration. If succeeded to share the mutex until the
|
||||
* time expiration, it returns `true` after calling the *closure*. Otherwise failed to
|
||||
* acquiring the shared lock in the given time, the function gives up the trial and returns
|
||||
* `false` without calling the *closure*.
|
||||
*
|
||||
* Failed to acquring the shared lock in the given time (returns `false`), it means that
|
||||
* there's someone who has already {@link ILockable.lock monopolied} the mutex and does not
|
||||
* return it over the time expiration.
|
||||
*
|
||||
* When succeeded to {@link ISharedLockable.lock_shared share} the mutex, the
|
||||
* {@link try_lock_until} function will call the *closure*, a custom function defning your
|
||||
* business. After the *closure* function be returned, the {@link try_lock} function
|
||||
* automatically {@link ISharedLockable.unlock_shared unlocks} the mutex, even if the
|
||||
* *closure* function throws any error.
|
||||
*
|
||||
* Therefore, when using this {@link try_lock_until} function, you don't need to consider
|
||||
* about {@link ISharedLockable.unlock_shared returning} the lock acquistion after your
|
||||
* business. It would just be done automatically.
|
||||
*
|
||||
* @param mutex Target mutex to try lock until time expiration.
|
||||
* @param at The maximum time point to wait.
|
||||
* @param closure A function defining your business.
|
||||
* @return Whether succeeded to share the mutex or not.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
export function try_lock_until<Mutex extends Pick<ISharedTimedLockable, "try_lock_shared_until" | "unlock_shared">>(mutex: Mutex, at: Date, closure: Closure): Promise<boolean>;
|
||||
/**
|
||||
* Type of closure function defining your business logic.
|
||||
*/
|
||||
type Closure = () => void | Promise<void>;
|
||||
export {};
|
||||
}
|
||||
-147
@@ -1,147 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SharedLock = void 0;
|
||||
var SafeLock_1 = require("../internal/thread/SafeLock");
|
||||
/**
|
||||
*
|
||||
*/
|
||||
var SharedLock = /** @class */ (function () {
|
||||
function SharedLock() {
|
||||
}
|
||||
return SharedLock;
|
||||
}());
|
||||
exports.SharedLock = SharedLock;
|
||||
/**
|
||||
* Shared mutex wrapper for the safe read lock.
|
||||
*
|
||||
* The module {@link SharedLock} is a collection of general purpose functions wrapping shared
|
||||
* mutex for ensuring the safe lock. If you *lock* a mutex (with your business logic code) through
|
||||
* any function of the {@link SharedLock} module, the shared mutex would be automatically
|
||||
* *unlocked* after your business, even if an error has been occured in your business.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
(function (SharedLock) {
|
||||
/**
|
||||
* Read locks a shared mutex with your business.
|
||||
*
|
||||
* Shares a mutex until be the *closure* has been completed. If there're someone who have
|
||||
* already {@link ILockable.lock monopolied} the mutex, the function call would be blocked
|
||||
* until all of them to {@link unlock return} their acquisitions.
|
||||
*
|
||||
* When succeeded to {@link ISharedLockable.lock_shared share} the mutex, the {@link lock}
|
||||
* function will call the *closure*, a custom function defning your business. After the
|
||||
* *closure* function be returned, the {@link lock} function automatically
|
||||
* {@link ISharedLockable.unlock_shared unlocks} the mutex, even if the *closure* function
|
||||
* throws any error.
|
||||
*
|
||||
* Therefore, when using this {@link lock} function, you don't need to consider about
|
||||
* {@link ISharedLockable.unlock_shared returning} the lock acquistion after your business.
|
||||
* It would just be done automatically.
|
||||
*
|
||||
* @param mutex Target shared mutex to read lock.
|
||||
* @param closure A function defining your business.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
function lock(mutex, closure) {
|
||||
return SafeLock_1.SafeLock.lock(function () { return mutex.lock_shared(); }, function () { return mutex.unlock_shared(); }, closure);
|
||||
}
|
||||
SharedLock.lock = lock;
|
||||
/**
|
||||
* Tries to read lock a shared mutex with your business.
|
||||
*
|
||||
* Attemps to share a mutex without blocking. If succeeded to share the mutex immediately, it
|
||||
* returns `true` directly. Otherwise there's someone who has already
|
||||
* {@link ILockable.lock monopolied} the mutex, the function gives up the trial immediately
|
||||
* and returns `false` directly without calling the *closure*.
|
||||
*
|
||||
* When succeeded to {@link ISharedLockable.lock_shared share} the mutex, the {@link try_lock}
|
||||
* function will call the *closure*, a custom function defning your business. After the
|
||||
* *closure* function be returned, the {@link try_lock} function automatically
|
||||
* {@link ISharedLockable.unlock_shared unlocks} the mutex, even if the *closure* function
|
||||
* throws any error.
|
||||
*
|
||||
* Therefore, when using this {@link try_lock} function, you don't need to consider about
|
||||
* {@link ISharedLockable.unlock_shared returning} the lock acquistion after your business.
|
||||
* It would just be done automatically.
|
||||
*
|
||||
* @param mutex Target shared mutex to try read lock.
|
||||
* @param closure A function defining your business.
|
||||
* @return Whether succeeded to share the mutex or not.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
function try_lock(mutex, closure) {
|
||||
return SafeLock_1.SafeLock.try_lock(function () { return mutex.try_lock_shared(); }, function () { return mutex.unlock_shared(); }, closure);
|
||||
}
|
||||
SharedLock.try_lock = try_lock;
|
||||
/**
|
||||
* Tries to read lock a shared mutex with your business until timeout.
|
||||
*
|
||||
* Attemps to share a mutex until timeout. If succeeded to share the mutex until timeout, it
|
||||
* returns `true` after calling the *closure*. Otherwise failed to acquiring the shared lock
|
||||
* in the given time, the function gives up the trial and returns `false` without calling the
|
||||
* *closure*.
|
||||
*
|
||||
* Failed to acquring the shared lock in the given time (returns `false`), it means that
|
||||
* there's someone who has already {@link ILockable.lock monopolied} the mutex and does not
|
||||
* return it over the timeout.
|
||||
*
|
||||
* When succeeded to {@link ISharedLockable.lock_shared share} the mutex, the
|
||||
* {@link try_lock_for} function will call the *closure*, a custom function defning your
|
||||
* business. After the *closure* function be returned, the {@link try_lock} function
|
||||
* automatically {@link ISharedLockable.unlock_shared unlocks} the mutex, even if the
|
||||
* *closure* function throws any error.
|
||||
*
|
||||
* Therefore, when using this {@link try_lock_for} function, you don't need to consider about
|
||||
* {@link ISharedLockable.unlock_shared returning} the lock acquistion after your business.
|
||||
* It would just be done automatically.
|
||||
*
|
||||
* @param mutex Target mutex to try lock until timeout.
|
||||
* @param ms The maximum miliseconds for waiting.
|
||||
* @param closure A function defining your business.
|
||||
* @return Whether succeeded to share the mutex or not.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
function try_lock_for(mutex, ms, closure) {
|
||||
return SafeLock_1.SafeLock.try_lock(function () { return mutex.try_lock_shared_for(ms); }, function () { return mutex.unlock_shared(); }, closure);
|
||||
}
|
||||
SharedLock.try_lock_for = try_lock_for;
|
||||
/**
|
||||
* Tries to read lock a shared mutex with your business until time expiration.
|
||||
*
|
||||
* Attemps to share a mutex until time expiration. If succeeded to share the mutex until the
|
||||
* time expiration, it returns `true` after calling the *closure*. Otherwise failed to
|
||||
* acquiring the shared lock in the given time, the function gives up the trial and returns
|
||||
* `false` without calling the *closure*.
|
||||
*
|
||||
* Failed to acquring the shared lock in the given time (returns `false`), it means that
|
||||
* there's someone who has already {@link ILockable.lock monopolied} the mutex and does not
|
||||
* return it over the time expiration.
|
||||
*
|
||||
* When succeeded to {@link ISharedLockable.lock_shared share} the mutex, the
|
||||
* {@link try_lock_until} function will call the *closure*, a custom function defning your
|
||||
* business. After the *closure* function be returned, the {@link try_lock} function
|
||||
* automatically {@link ISharedLockable.unlock_shared unlocks} the mutex, even if the
|
||||
* *closure* function throws any error.
|
||||
*
|
||||
* Therefore, when using this {@link try_lock_until} function, you don't need to consider
|
||||
* about {@link ISharedLockable.unlock_shared returning} the lock acquistion after your
|
||||
* business. It would just be done automatically.
|
||||
*
|
||||
* @param mutex Target mutex to try lock until time expiration.
|
||||
* @param at The maximum time point to wait.
|
||||
* @param closure A function defining your business.
|
||||
* @return Whether succeeded to share the mutex or not.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
function try_lock_until(mutex, at, closure) {
|
||||
return SafeLock_1.SafeLock.try_lock(function () { return mutex.try_lock_shared_until(at); }, function () { return mutex.unlock_shared(); }, closure);
|
||||
}
|
||||
SharedLock.try_lock_until = try_lock_until;
|
||||
})(SharedLock = exports.SharedLock || (exports.SharedLock = {}));
|
||||
exports.SharedLock = SharedLock;
|
||||
//# sourceMappingURL=SharedLock.js.map
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
import { ISharedLockable } from "../base/thread/ISharedLockable";
|
||||
/**
|
||||
* Shared mutex.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class SharedMutex implements ISharedLockable {
|
||||
private mutex_;
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
constructor();
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
lock(): Promise<void>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
try_lock(): Promise<boolean>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
unlock(): Promise<void>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
lock_shared(): Promise<void>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
try_lock_shared(): Promise<boolean>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
unlock_shared(): Promise<void>;
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SharedMutex = void 0;
|
||||
var SharedTimedMutex_1 = require("./SharedTimedMutex");
|
||||
/**
|
||||
* Shared mutex.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var SharedMutex = /** @class */ (function () {
|
||||
/* ---------------------------------------------------------
|
||||
CONSTRUCTOR
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
function SharedMutex() {
|
||||
this.mutex_ = new SharedTimedMutex_1.SharedTimedMutex(this);
|
||||
}
|
||||
/* ---------------------------------------------------------
|
||||
WRITE LOCK
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedMutex.prototype.lock = function () {
|
||||
return this.mutex_.lock();
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedMutex.prototype.try_lock = function () {
|
||||
return this.mutex_.try_lock();
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedMutex.prototype.unlock = function () {
|
||||
return this.mutex_.unlock();
|
||||
};
|
||||
/* ---------------------------------------------------------
|
||||
READ LOCK
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedMutex.prototype.lock_shared = function () {
|
||||
return this.mutex_.lock_shared();
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedMutex.prototype.try_lock_shared = function () {
|
||||
return this.mutex_.try_lock_shared();
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedMutex.prototype.unlock_shared = function () {
|
||||
return this.mutex_.unlock_shared();
|
||||
};
|
||||
return SharedMutex;
|
||||
}());
|
||||
exports.SharedMutex = SharedMutex;
|
||||
//# sourceMappingURL=SharedMutex.js.map
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
import { ISharedTimedLockable } from "../base/thread/ISharedTimedLockable";
|
||||
/**
|
||||
* Shared timed mutex.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class SharedTimedMutex implements ISharedTimedLockable {
|
||||
private source_;
|
||||
private queue_;
|
||||
private writing_;
|
||||
private reading_;
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
constructor();
|
||||
private _Current_access_type;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
lock(): Promise<void>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
try_lock(): Promise<boolean>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
try_lock_for(ms: number): Promise<boolean>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
try_lock_until(at: Date): Promise<boolean>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
unlock(): Promise<void>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
lock_shared(): Promise<void>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
try_lock_shared(): Promise<boolean>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
try_lock_shared_for(ms: number): Promise<boolean>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
try_lock_shared_until(at: Date): Promise<boolean>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
unlock_shared(): Promise<void>;
|
||||
private _Release;
|
||||
private _Cancel;
|
||||
}
|
||||
-355
@@ -1,355 +0,0 @@
|
||||
"use strict";
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var __values = (this && this.__values) || function(o) {
|
||||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
||||
if (m) return m.call(o);
|
||||
if (o && typeof o.length === "number") return {
|
||||
next: function () {
|
||||
if (o && i >= o.length) o = void 0;
|
||||
return { value: o && o[i++], done: !o };
|
||||
}
|
||||
};
|
||||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SharedTimedMutex = void 0;
|
||||
var List_1 = require("../container/List");
|
||||
var InvalidArgument_1 = require("../exception/InvalidArgument");
|
||||
var global_1 = require("./global");
|
||||
/**
|
||||
* Shared timed mutex.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var SharedTimedMutex = /** @class */ (function () {
|
||||
function SharedTimedMutex(source) {
|
||||
if (source === void 0) { source = null; }
|
||||
this.source_ = source !== null ? source : this;
|
||||
this.queue_ = new List_1.List();
|
||||
this.writing_ = 0;
|
||||
this.reading_ = 0;
|
||||
}
|
||||
SharedTimedMutex.prototype._Current_access_type = function () {
|
||||
return this.queue_.empty() ? null : this.queue_.front().accessType;
|
||||
};
|
||||
/* ---------------------------------------------------------
|
||||
WRITE LOCK
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedTimedMutex.prototype.lock = function () {
|
||||
var _this = this;
|
||||
return new Promise(function (resolve) {
|
||||
// CONSTRUCT RESOLVER
|
||||
var resolver = {
|
||||
handler: _this.writing_++ === 0 && _this.reading_ === 0
|
||||
? null
|
||||
: resolve,
|
||||
accessType: 0 /* AccessType.WRITE */,
|
||||
lockType: 0 /* LockType.HOLD */,
|
||||
};
|
||||
_this.queue_.push_back(resolver);
|
||||
// LOCK OR WAIT
|
||||
if (resolver.handler === null)
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedTimedMutex.prototype.try_lock = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
// LOCKABLE ?
|
||||
if (this.writing_ !== 0 || this.reading_ !== 0)
|
||||
return [2 /*return*/, false];
|
||||
// CONSTRUCT RESOLVER
|
||||
this.queue_.push_back({
|
||||
handler: null,
|
||||
accessType: 0 /* AccessType.WRITE */,
|
||||
lockType: 1 /* LockType.KNOCK */,
|
||||
});
|
||||
// RETURNS
|
||||
++this.writing_;
|
||||
return [2 /*return*/, true];
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedTimedMutex.prototype.try_lock_for = function (ms) {
|
||||
var _this = this;
|
||||
return new Promise(function (resolve) {
|
||||
// CONSTRUCT RESOLVER
|
||||
var it = _this.queue_.insert(_this.queue_.end(), {
|
||||
handler: _this.writing_++ === 0 && _this.reading_ === 0
|
||||
? null
|
||||
: resolve,
|
||||
accessType: 0 /* AccessType.WRITE */,
|
||||
lockType: 1 /* LockType.KNOCK */,
|
||||
});
|
||||
if (it.value.handler === null)
|
||||
resolve(true); // SUCCESS
|
||||
else {
|
||||
// AUTOMATIC UNLOCK AFTER TIMEOUT
|
||||
(0, global_1.sleep_for)(ms).then(function () {
|
||||
// NOT YET, THEN DO UNLOCK
|
||||
if (it.value.handler !== null) {
|
||||
--_this.writing_;
|
||||
_this._Cancel(it);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedTimedMutex.prototype.try_lock_until = function (at) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var now, ms;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
now = new Date();
|
||||
ms = at.getTime() - now.getTime();
|
||||
return [4 /*yield*/, this.try_lock_for(ms)];
|
||||
case 1: return [2 /*return*/, _a.sent()];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedTimedMutex.prototype.unlock = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
if (this._Current_access_type() !== 0 /* AccessType.WRITE */)
|
||||
throw new InvalidArgument_1.InvalidArgument("Error on std.".concat(this.source_.constructor.name, ".unlock(): this mutex is free on the unique lock."));
|
||||
--this.writing_;
|
||||
this.queue_.pop_front();
|
||||
this._Release();
|
||||
return [2 /*return*/];
|
||||
});
|
||||
});
|
||||
};
|
||||
/* ---------------------------------------------------------
|
||||
READ LOCK
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedTimedMutex.prototype.lock_shared = function () {
|
||||
var _this = this;
|
||||
return new Promise(function (resolve) {
|
||||
var resolver = {
|
||||
handler: _this.writing_ === 0 ? null : resolve,
|
||||
accessType: 1 /* AccessType.READ */,
|
||||
lockType: 0 /* LockType.HOLD */,
|
||||
};
|
||||
_this.queue_.push_back(resolver);
|
||||
++_this.reading_;
|
||||
if (resolver.handler === null)
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedTimedMutex.prototype.try_lock_shared = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
if (this.writing_ !== 0)
|
||||
return [2 /*return*/, false];
|
||||
++this.reading_;
|
||||
this.queue_.push_back({
|
||||
handler: null,
|
||||
accessType: 1 /* AccessType.READ */,
|
||||
lockType: 1 /* LockType.KNOCK */,
|
||||
});
|
||||
return [2 /*return*/, true];
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedTimedMutex.prototype.try_lock_shared_for = function (ms) {
|
||||
var _this = this;
|
||||
return new Promise(function (resolve) {
|
||||
// CONSTRUCT RESOLVER
|
||||
var it = _this.queue_.insert(_this.queue_.end(), {
|
||||
handler: _this.writing_ === 0 ? null : resolve,
|
||||
accessType: 1 /* AccessType.READ */,
|
||||
lockType: 1 /* LockType.KNOCK */,
|
||||
});
|
||||
++_this.reading_;
|
||||
if (it.value.handler === null)
|
||||
resolve(true);
|
||||
else {
|
||||
// AUTOMATIC UNLOCK AFTER TIMEOUT
|
||||
(0, global_1.sleep_for)(ms).then(function () {
|
||||
// NOT YET, THEN DO UNLOCK
|
||||
if (it.value.handler !== null) {
|
||||
--_this.reading_;
|
||||
_this._Cancel(it);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedTimedMutex.prototype.try_lock_shared_until = function (at) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var now, ms;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
now = new Date();
|
||||
ms = at.getTime() - now.getTime();
|
||||
return [4 /*yield*/, this.try_lock_shared_for(ms)];
|
||||
case 1: return [2 /*return*/, _a.sent()];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SharedTimedMutex.prototype.unlock_shared = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
if (this._Current_access_type() !== 1 /* AccessType.READ */)
|
||||
throw new InvalidArgument_1.InvalidArgument("Error on std.".concat(this.source_.constructor.name, ".unlock_shared(): this mutex is free on the shared lock."));
|
||||
--this.reading_;
|
||||
this.queue_.pop_front();
|
||||
this._Release();
|
||||
return [2 /*return*/];
|
||||
});
|
||||
});
|
||||
};
|
||||
/* ---------------------------------------------------------
|
||||
RELEASE
|
||||
--------------------------------------------------------- */
|
||||
SharedTimedMutex.prototype._Release = function () {
|
||||
var e_1, _a, e_2, _b;
|
||||
// STEP TO THE NEXT LOCKS
|
||||
var current = this._Current_access_type();
|
||||
var resolverList = [];
|
||||
try {
|
||||
for (var _c = __values(this.queue_), _d = _c.next(); !_d.done; _d = _c.next()) {
|
||||
var resolver = _d.value;
|
||||
// DIFFERENT ACCESS TYPE COMES?
|
||||
if (resolver.accessType !== current)
|
||||
break;
|
||||
// COPY AND CLEAR
|
||||
else if (resolver.handler !== null) {
|
||||
resolverList.push(__assign({}, resolver));
|
||||
resolver.handler = null;
|
||||
}
|
||||
// STOP AFTER WRITE LOCK
|
||||
if (resolver.accessType === 0 /* AccessType.WRITE */)
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
||||
}
|
||||
finally { if (e_1) throw e_1.error; }
|
||||
}
|
||||
try {
|
||||
// CALL THE HANDLERS
|
||||
for (var resolverList_1 = __values(resolverList), resolverList_1_1 = resolverList_1.next(); !resolverList_1_1.done; resolverList_1_1 = resolverList_1.next()) {
|
||||
var resolver = resolverList_1_1.value;
|
||||
if (resolver.lockType === 0 /* LockType.HOLD */)
|
||||
resolver.handler();
|
||||
else
|
||||
resolver.handler(true);
|
||||
}
|
||||
}
|
||||
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (resolverList_1_1 && !resolverList_1_1.done && (_b = resolverList_1.return)) _b.call(resolverList_1);
|
||||
}
|
||||
finally { if (e_2) throw e_2.error; }
|
||||
}
|
||||
};
|
||||
SharedTimedMutex.prototype._Cancel = function (it) {
|
||||
//----
|
||||
// POP THE RELEASE
|
||||
//----
|
||||
// DO RASE
|
||||
this.queue_.erase(it);
|
||||
// EXTRACT HANDLER TO AVOID THE `this._Release()`
|
||||
var handler = it.value.handler;
|
||||
it.value.handler = null;
|
||||
//----
|
||||
// POST-PROCESS
|
||||
//----
|
||||
// CHECK THE PREVIOUS RESOLVER
|
||||
var prev = it.prev();
|
||||
// RELEASE IF IT IS THE LASTEST RESOLVER
|
||||
if (prev.equals(this.queue_.end()) === false &&
|
||||
prev.value.handler === null)
|
||||
this._Release();
|
||||
// (LAZY) RETURNS FAILURE
|
||||
handler(false);
|
||||
};
|
||||
return SharedTimedMutex;
|
||||
}());
|
||||
exports.SharedTimedMutex = SharedTimedMutex;
|
||||
//# sourceMappingURL=SharedTimedMutex.js.map
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* Singleton generator.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class Singleton<T, Args extends any[] = []> {
|
||||
private readonly closure_;
|
||||
private value_;
|
||||
constructor(closure: (...args: Args) => T);
|
||||
get(...args: Args): T;
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
"use strict";
|
||||
var __read = (this && this.__read) || function (o, n) {
|
||||
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
||||
if (!m) return o;
|
||||
var i = m.call(o), r, ar = [], e;
|
||||
try {
|
||||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
||||
}
|
||||
catch (error) { e = { error: error }; }
|
||||
finally {
|
||||
try {
|
||||
if (r && !r.done && (m = i["return"])) m.call(i);
|
||||
}
|
||||
finally { if (e) throw e.error; }
|
||||
}
|
||||
return ar;
|
||||
};
|
||||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
||||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
||||
if (ar || !(i in from)) {
|
||||
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
||||
ar[i] = from[i];
|
||||
}
|
||||
}
|
||||
return to.concat(ar || Array.prototype.slice.call(from));
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Singleton = void 0;
|
||||
/**
|
||||
* Singleton generator.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var Singleton = /** @class */ (function () {
|
||||
function Singleton(closure) {
|
||||
this.closure_ = closure;
|
||||
this.value_ = NOT_MOUNTED_YET;
|
||||
}
|
||||
Singleton.prototype.get = function () {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
if (this.value_ === NOT_MOUNTED_YET)
|
||||
this.value_ = this.closure_.apply(this, __spreadArray([], __read(args), false));
|
||||
return this.value_;
|
||||
};
|
||||
return Singleton;
|
||||
}());
|
||||
exports.Singleton = Singleton;
|
||||
var NOT_MOUNTED_YET = {};
|
||||
//# sourceMappingURL=Singleton.js.map
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
import { ITimedLockable } from "../base/thread/ITimedLockable";
|
||||
/**
|
||||
* Timed mutex.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class TimedMutex implements ITimedLockable {
|
||||
private mutex_;
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
constructor();
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
lock(): Promise<void>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
try_lock(): Promise<boolean>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
unlock(): Promise<void>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
try_lock_for(ms: number): Promise<boolean>;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
try_lock_until(at: Date): Promise<boolean>;
|
||||
}
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TimedMutex = void 0;
|
||||
var SharedTimedMutex_1 = require("./SharedTimedMutex");
|
||||
/**
|
||||
* Timed mutex.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var TimedMutex = /** @class */ (function () {
|
||||
/* ---------------------------------------------------------
|
||||
CONSTRUCTOR
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
function TimedMutex() {
|
||||
this.mutex_ = new SharedTimedMutex_1.SharedTimedMutex(this);
|
||||
}
|
||||
/* ---------------------------------------------------------
|
||||
LOCK & UNLOCK
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TimedMutex.prototype.lock = function () {
|
||||
return this.mutex_.lock();
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TimedMutex.prototype.try_lock = function () {
|
||||
return this.mutex_.try_lock();
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TimedMutex.prototype.unlock = function () {
|
||||
return this.mutex_.unlock();
|
||||
};
|
||||
/* ---------------------------------------------------------
|
||||
TIMED LOCK
|
||||
--------------------------------------------------------- */
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TimedMutex.prototype.try_lock_for = function (ms) {
|
||||
return this.mutex_.try_lock_for(ms);
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TimedMutex.prototype.try_lock_until = function (at) {
|
||||
return this.mutex_.try_lock_until(at);
|
||||
};
|
||||
return TimedMutex;
|
||||
}());
|
||||
exports.TimedMutex = TimedMutex;
|
||||
//# sourceMappingURL=TimedMutex.js.map
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Timed singleton generator.
|
||||
*
|
||||
* The `TimedSingleton` is a type of {@link Singleton} class who re-constructs the singleton
|
||||
* value repeatedly whenever specific time has been elapsed after the last lazy construction.
|
||||
*
|
||||
* @template T Type of the value to be lazy-constructed
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class TimedSingleton<T, Args extends any[] = []> {
|
||||
private readonly interval_;
|
||||
private readonly closure_;
|
||||
private expired_at_;
|
||||
private value_;
|
||||
/**
|
||||
* Initializer Constructor.
|
||||
*
|
||||
* @param interval Specific interval time, to determine whether re-generation of the singleton value is required or not, as milliseconds
|
||||
* @param closure Lazy constructor function returning the target value
|
||||
*/
|
||||
constructor(interval: number, closure: (...args: Args) => T);
|
||||
/**
|
||||
* Get value.
|
||||
*
|
||||
* @returns The lazy constructed value
|
||||
*/
|
||||
get(...args: Args): T;
|
||||
}
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
"use strict";
|
||||
var __read = (this && this.__read) || function (o, n) {
|
||||
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
||||
if (!m) return o;
|
||||
var i = m.call(o), r, ar = [], e;
|
||||
try {
|
||||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
||||
}
|
||||
catch (error) { e = { error: error }; }
|
||||
finally {
|
||||
try {
|
||||
if (r && !r.done && (m = i["return"])) m.call(i);
|
||||
}
|
||||
finally { if (e) throw e.error; }
|
||||
}
|
||||
return ar;
|
||||
};
|
||||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
||||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
||||
if (ar || !(i in from)) {
|
||||
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
||||
ar[i] = from[i];
|
||||
}
|
||||
}
|
||||
return to.concat(ar || Array.prototype.slice.call(from));
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TimedSingleton = void 0;
|
||||
/**
|
||||
* Timed singleton generator.
|
||||
*
|
||||
* The `TimedSingleton` is a type of {@link Singleton} class who re-constructs the singleton
|
||||
* value repeatedly whenever specific time has been elapsed after the last lazy construction.
|
||||
*
|
||||
* @template T Type of the value to be lazy-constructed
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var TimedSingleton = /** @class */ (function () {
|
||||
/**
|
||||
* Initializer Constructor.
|
||||
*
|
||||
* @param interval Specific interval time, to determine whether re-generation of the singleton value is required or not, as milliseconds
|
||||
* @param closure Lazy constructor function returning the target value
|
||||
*/
|
||||
function TimedSingleton(interval, closure) {
|
||||
this.interval_ = interval;
|
||||
this.closure_ = closure;
|
||||
this.value_ = null;
|
||||
this.expired_at_ = 0;
|
||||
}
|
||||
/**
|
||||
* Get value.
|
||||
*
|
||||
* @returns The lazy constructed value
|
||||
*/
|
||||
TimedSingleton.prototype.get = function () {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
if (Date.now() >= this.expired_at_) {
|
||||
this.expired_at_ = Date.now() + this.interval_;
|
||||
this.value_ = this.closure_.apply(this, __spreadArray([], __read(args), false));
|
||||
}
|
||||
return this.value_;
|
||||
};
|
||||
return TimedSingleton;
|
||||
}());
|
||||
exports.TimedSingleton = TimedSingleton;
|
||||
//# sourceMappingURL=TimedSingleton.js.map
|
||||
-137
@@ -1,137 +0,0 @@
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
import { ILockable } from "../base/thread/ILockable";
|
||||
import { ITimedLockable } from "../base/thread/ITimedLockable";
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export declare class UniqueLock {
|
||||
}
|
||||
/**
|
||||
* Mutex wrapper for the safe write lock.
|
||||
*
|
||||
* The module {@link UniqueLock} is a collection of general purpose functions wrapping mutex for
|
||||
* ensuring the safe lock. If you *lock* a mutex (with your business logic code) through any
|
||||
* function of the {@link UniqueLock} module, the mutex would be automatically *unlocked* after
|
||||
* your business, even if an error has been occured in your business.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare namespace UniqueLock {
|
||||
/**
|
||||
* Write locks a mutex with your business logic code.
|
||||
*
|
||||
* Monopolies a mutex until be the *closure* has been completed. If there're someone who have
|
||||
* already {@link ILockable.lock monopolied} or {@link ISharedLockable.lock shared} the mutex,
|
||||
* the function call would be blocked until all of them return their acquisitions by calling
|
||||
* {@link ILockable.unlock} or {@link ISharedLockable.unlock_shared} methods.
|
||||
*
|
||||
* When succeeded to {@link ILockable.lock monopoly} the mutex, the {@link lock} function will
|
||||
* call the *closure*, a custom function definig your business. After the *closure* function
|
||||
* be returned, the {@link lock} function automatically {@link ILockable.unlock unlocks} the
|
||||
* mutex, even if the *closure* function throws any error.
|
||||
*
|
||||
* Therefore, when using this {@link lock} function, you don't need to consider about
|
||||
* {@link ILockable.unlock returning} the lock acquistion after your business. It would just
|
||||
* be done automatically.
|
||||
*
|
||||
* @param mutex Target mutex to write lock.
|
||||
* @param closure A function defining your business.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
export function lock<Mutex extends Pick<ILockable, "lock" | "unlock">>(mutex: Mutex, closure: Closure): Promise<void>;
|
||||
/**
|
||||
* Tries to write lock a mutex with your business.
|
||||
*
|
||||
* Attempts to monopoly a mutex without blocking. If succeeded to monopoly the mutex
|
||||
* immediately, it returns `true` after calling the *closure*. Otherwise there's someone who
|
||||
* has already {@link ILockable.lock monopolied} or {@link ISharedLockable.lock shared} the
|
||||
* mutex, the function gives up the trial immediately and returns `false` directly without
|
||||
* calling the *closure*.
|
||||
*
|
||||
* When succeeded to {@link ILockable.lock monopoly} the mutex, the {@link try_lock} function
|
||||
* will call the *closure*, a custom function definig your business. After the *closure*
|
||||
* function be returned, the {@link try_lock} function automatically
|
||||
* {@link ILockable.unlock unlocks} the mutex, even if the *closure* function throws any
|
||||
* error.
|
||||
*
|
||||
* Therefore, when using this {@link try_lock} function, you don't need to consider about
|
||||
* {@link ILockable.unlock returning} the lock acquistion after your business. It would just
|
||||
* be done automatically.
|
||||
*
|
||||
* @param mutex Target mutex to try write lock.
|
||||
* @param closure A function defining your business.
|
||||
* @return Whether succeeded to monopoly the mutex or not.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
export function try_lock<Mutex extends Pick<ILockable, "try_lock" | "unlock">>(mutex: Mutex, closure: Closure): Promise<boolean>;
|
||||
/**
|
||||
* Tries to write lock a mutex with your business until timeout.
|
||||
*
|
||||
* Attempts to monopoly a mutex until timeout. If succeeded to monopoly the mutex until the
|
||||
* timeout, it returns `true` after calling the *closure*. Otherwise failed to acquiring the
|
||||
* lock in the given time, the function gives up the trial and returns `false` without calling
|
||||
* the *closure*.
|
||||
*
|
||||
* Failed to acquiring the lock in the given time (returns `false`), it means that there's
|
||||
* someone who has already {@link ILockable.lock monopolied} or {@link ISharedLockable.lock}
|
||||
* the mutex and does not return it over the timeout.
|
||||
*
|
||||
* When succeeded to {@link ILockable.lock monopoly} the mutex, the {@link try_lock_for}
|
||||
* function will call the *closure*, a custom function definig your business. After the
|
||||
* *closure* function be returned, the {@link try_lock_for} function automatically
|
||||
* {@link ILockable.unlock unlocks} the mutex and returns `true`, even if the *closure*
|
||||
* function throws any error.
|
||||
*
|
||||
* Therefore, when using this {@link try_lock_for} function, you don't need to consider about
|
||||
* {@link ILockable.unlock returning} the lock acquistion after your business. It would just
|
||||
* be done automatically.
|
||||
*
|
||||
* @param mutex Target mutex to try write lock until timeout.
|
||||
* @param ms The maximum miliseconds for waiting.
|
||||
* @param closure A function defining your business.
|
||||
* @return Whether succeeded to monopoly the mutex or not.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
export function try_lock_for<Mutex extends Pick<ITimedLockable, "try_lock_for" | "unlock">>(mutex: Mutex, ms: number, closure: Closure): Promise<boolean>;
|
||||
/**
|
||||
* Tries to write lock a mutex with your business until time expiration.
|
||||
*
|
||||
* Attempts to monopoly a mutex until time expiration. If succeeded to monopoly the mutex
|
||||
* until the time expiration, it returns `true` after calling the *closure*. Otherwise failed
|
||||
* to acquiring the lock in the given time, the function gives up the trial and returns
|
||||
* `false` without calling the *closure*.
|
||||
*
|
||||
* Failed to acquiring the lock in the given time (returns `false`), it means that there's
|
||||
* someone who has already {@link ILockable.lock monopolied} or {@link ISharedLockable.lock}
|
||||
* the mutex and does not return it over the time expiration.
|
||||
*
|
||||
* When succeeded to {@link ILockable.lock monopoly} the mutex, the {@link try_lock_until}
|
||||
* function will call the *closure*, a custom function definig your business. After the
|
||||
* *closure* function be returned, the {@link try_lock_until} function automatically
|
||||
* {@link ILockable.unlock unlocks} the mutex and returns `true`, even if the *closure*
|
||||
* function throws any error.
|
||||
*
|
||||
* TTherefore, when using this {@link try_lock_until} function, you don't need to consider
|
||||
* about {@link ILockable.unlock returning} the lock acquistion after your business. It would
|
||||
* just be done automatically.
|
||||
*
|
||||
* @param mutex Target mutex to try write lock until time expiration.
|
||||
* @param at The maximum time point to wait.
|
||||
* @param closure A function defining your business.
|
||||
* @return Whether succeeded to monopoly the mutex or not.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
export function try_lock_until<Mutex extends Pick<ITimedLockable, "try_lock_until" | "unlock">>(mutex: Mutex, at: Date, closure: Closure): Promise<boolean>;
|
||||
/**
|
||||
* Type of closure function defining your business logic.
|
||||
*/
|
||||
type Closure = () => void | Promise<void>;
|
||||
export {};
|
||||
}
|
||||
-148
@@ -1,148 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UniqueLock = void 0;
|
||||
var SafeLock_1 = require("../internal/thread/SafeLock");
|
||||
/**
|
||||
*
|
||||
*/
|
||||
var UniqueLock = /** @class */ (function () {
|
||||
function UniqueLock() {
|
||||
}
|
||||
return UniqueLock;
|
||||
}());
|
||||
exports.UniqueLock = UniqueLock;
|
||||
/**
|
||||
* Mutex wrapper for the safe write lock.
|
||||
*
|
||||
* The module {@link UniqueLock} is a collection of general purpose functions wrapping mutex for
|
||||
* ensuring the safe lock. If you *lock* a mutex (with your business logic code) through any
|
||||
* function of the {@link UniqueLock} module, the mutex would be automatically *unlocked* after
|
||||
* your business, even if an error has been occured in your business.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
(function (UniqueLock) {
|
||||
/**
|
||||
* Write locks a mutex with your business logic code.
|
||||
*
|
||||
* Monopolies a mutex until be the *closure* has been completed. If there're someone who have
|
||||
* already {@link ILockable.lock monopolied} or {@link ISharedLockable.lock shared} the mutex,
|
||||
* the function call would be blocked until all of them return their acquisitions by calling
|
||||
* {@link ILockable.unlock} or {@link ISharedLockable.unlock_shared} methods.
|
||||
*
|
||||
* When succeeded to {@link ILockable.lock monopoly} the mutex, the {@link lock} function will
|
||||
* call the *closure*, a custom function definig your business. After the *closure* function
|
||||
* be returned, the {@link lock} function automatically {@link ILockable.unlock unlocks} the
|
||||
* mutex, even if the *closure* function throws any error.
|
||||
*
|
||||
* Therefore, when using this {@link lock} function, you don't need to consider about
|
||||
* {@link ILockable.unlock returning} the lock acquistion after your business. It would just
|
||||
* be done automatically.
|
||||
*
|
||||
* @param mutex Target mutex to write lock.
|
||||
* @param closure A function defining your business.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
function lock(mutex, closure) {
|
||||
return SafeLock_1.SafeLock.lock(function () { return mutex.lock(); }, function () { return mutex.unlock(); }, closure);
|
||||
}
|
||||
UniqueLock.lock = lock;
|
||||
/**
|
||||
* Tries to write lock a mutex with your business.
|
||||
*
|
||||
* Attempts to monopoly a mutex without blocking. If succeeded to monopoly the mutex
|
||||
* immediately, it returns `true` after calling the *closure*. Otherwise there's someone who
|
||||
* has already {@link ILockable.lock monopolied} or {@link ISharedLockable.lock shared} the
|
||||
* mutex, the function gives up the trial immediately and returns `false` directly without
|
||||
* calling the *closure*.
|
||||
*
|
||||
* When succeeded to {@link ILockable.lock monopoly} the mutex, the {@link try_lock} function
|
||||
* will call the *closure*, a custom function definig your business. After the *closure*
|
||||
* function be returned, the {@link try_lock} function automatically
|
||||
* {@link ILockable.unlock unlocks} the mutex, even if the *closure* function throws any
|
||||
* error.
|
||||
*
|
||||
* Therefore, when using this {@link try_lock} function, you don't need to consider about
|
||||
* {@link ILockable.unlock returning} the lock acquistion after your business. It would just
|
||||
* be done automatically.
|
||||
*
|
||||
* @param mutex Target mutex to try write lock.
|
||||
* @param closure A function defining your business.
|
||||
* @return Whether succeeded to monopoly the mutex or not.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
function try_lock(mutex, closure) {
|
||||
return SafeLock_1.SafeLock.try_lock(function () { return mutex.try_lock(); }, function () { return mutex.unlock(); }, closure);
|
||||
}
|
||||
UniqueLock.try_lock = try_lock;
|
||||
/**
|
||||
* Tries to write lock a mutex with your business until timeout.
|
||||
*
|
||||
* Attempts to monopoly a mutex until timeout. If succeeded to monopoly the mutex until the
|
||||
* timeout, it returns `true` after calling the *closure*. Otherwise failed to acquiring the
|
||||
* lock in the given time, the function gives up the trial and returns `false` without calling
|
||||
* the *closure*.
|
||||
*
|
||||
* Failed to acquiring the lock in the given time (returns `false`), it means that there's
|
||||
* someone who has already {@link ILockable.lock monopolied} or {@link ISharedLockable.lock}
|
||||
* the mutex and does not return it over the timeout.
|
||||
*
|
||||
* When succeeded to {@link ILockable.lock monopoly} the mutex, the {@link try_lock_for}
|
||||
* function will call the *closure*, a custom function definig your business. After the
|
||||
* *closure* function be returned, the {@link try_lock_for} function automatically
|
||||
* {@link ILockable.unlock unlocks} the mutex and returns `true`, even if the *closure*
|
||||
* function throws any error.
|
||||
*
|
||||
* Therefore, when using this {@link try_lock_for} function, you don't need to consider about
|
||||
* {@link ILockable.unlock returning} the lock acquistion after your business. It would just
|
||||
* be done automatically.
|
||||
*
|
||||
* @param mutex Target mutex to try write lock until timeout.
|
||||
* @param ms The maximum miliseconds for waiting.
|
||||
* @param closure A function defining your business.
|
||||
* @return Whether succeeded to monopoly the mutex or not.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
function try_lock_for(mutex, ms, closure) {
|
||||
return SafeLock_1.SafeLock.try_lock(function () { return mutex.try_lock_for(ms); }, function () { return mutex.unlock(); }, closure);
|
||||
}
|
||||
UniqueLock.try_lock_for = try_lock_for;
|
||||
/**
|
||||
* Tries to write lock a mutex with your business until time expiration.
|
||||
*
|
||||
* Attempts to monopoly a mutex until time expiration. If succeeded to monopoly the mutex
|
||||
* until the time expiration, it returns `true` after calling the *closure*. Otherwise failed
|
||||
* to acquiring the lock in the given time, the function gives up the trial and returns
|
||||
* `false` without calling the *closure*.
|
||||
*
|
||||
* Failed to acquiring the lock in the given time (returns `false`), it means that there's
|
||||
* someone who has already {@link ILockable.lock monopolied} or {@link ISharedLockable.lock}
|
||||
* the mutex and does not return it over the time expiration.
|
||||
*
|
||||
* When succeeded to {@link ILockable.lock monopoly} the mutex, the {@link try_lock_until}
|
||||
* function will call the *closure*, a custom function definig your business. After the
|
||||
* *closure* function be returned, the {@link try_lock_until} function automatically
|
||||
* {@link ILockable.unlock unlocks} the mutex and returns `true`, even if the *closure*
|
||||
* function throws any error.
|
||||
*
|
||||
* TTherefore, when using this {@link try_lock_until} function, you don't need to consider
|
||||
* about {@link ILockable.unlock returning} the lock acquistion after your business. It would
|
||||
* just be done automatically.
|
||||
*
|
||||
* @param mutex Target mutex to try write lock until time expiration.
|
||||
* @param at The maximum time point to wait.
|
||||
* @param closure A function defining your business.
|
||||
* @return Whether succeeded to monopoly the mutex or not.
|
||||
*
|
||||
* @throw Exception would be thrown if the *closure* function throws any error.
|
||||
*/
|
||||
function try_lock_until(mutex, at, closure) {
|
||||
return SafeLock_1.SafeLock.try_lock(function () { return mutex.try_lock_until(at); }, function () { return mutex.unlock(); }, closure);
|
||||
}
|
||||
UniqueLock.try_lock_until = try_lock_until;
|
||||
})(UniqueLock = exports.UniqueLock || (exports.UniqueLock = {}));
|
||||
exports.UniqueLock = UniqueLock;
|
||||
//# sourceMappingURL=UniqueLock.js.map
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* Variadic mutable singleton generator.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class VariadicMutableSingleton<T, Args extends any[]> {
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
private readonly closure_;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
private readonly dict_;
|
||||
constructor(closure: (...args: Args) => Promise<T>, hashFunc?: (args: Args) => number, pred?: (x: Args, y: Args) => boolean);
|
||||
set(...items: [...Args, T]): Promise<void>;
|
||||
reload(...args: Args): Promise<T>;
|
||||
clear(): Promise<void>;
|
||||
clear(...args: Args): Promise<void>;
|
||||
get(...args: Args): Promise<T>;
|
||||
is_loaded(...args: Args): Promise<boolean>;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
private _Get_singleton;
|
||||
}
|
||||
-158
@@ -1,158 +0,0 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var __read = (this && this.__read) || function (o, n) {
|
||||
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
||||
if (!m) return o;
|
||||
var i = m.call(o), r, ar = [], e;
|
||||
try {
|
||||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
||||
}
|
||||
catch (error) { e = { error: error }; }
|
||||
finally {
|
||||
try {
|
||||
if (r && !r.done && (m = i["return"])) m.call(i);
|
||||
}
|
||||
finally { if (e) throw e.error; }
|
||||
}
|
||||
return ar;
|
||||
};
|
||||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
||||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
||||
if (ar || !(i in from)) {
|
||||
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
||||
ar[i] = from[i];
|
||||
}
|
||||
}
|
||||
return to.concat(ar || Array.prototype.slice.call(from));
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.VariadicMutableSingleton = void 0;
|
||||
//================================================================
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
//================================================================
|
||||
var HashMap_1 = require("../container/HashMap");
|
||||
var MutableSingleton_1 = require("./MutableSingleton");
|
||||
var iterations_1 = require("../ranges/algorithm/iterations");
|
||||
var hash_1 = require("../functional/hash");
|
||||
/**
|
||||
* Variadic mutable singleton generator.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var VariadicMutableSingleton = /** @class */ (function () {
|
||||
/* ---------------------------------------------------------------
|
||||
CONSTRUCTORS
|
||||
--------------------------------------------------------------- */
|
||||
function VariadicMutableSingleton(closure, hashFunc, pred) {
|
||||
if (hashFunc === void 0) { hashFunc = function (args) { return hash_1.hash.apply(void 0, __spreadArray([], __read(args), false)); }; }
|
||||
if (pred === void 0) { pred = iterations_1.equal; }
|
||||
this.closure_ = closure;
|
||||
this.dict_ = new HashMap_1.HashMap(hashFunc, pred);
|
||||
}
|
||||
VariadicMutableSingleton.prototype.set = function () {
|
||||
var items = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
items[_i] = arguments[_i];
|
||||
}
|
||||
var args = items.slice(0, items.length - 1);
|
||||
var value = items[items.length - 1];
|
||||
return this._Get_singleton(args).set(value);
|
||||
};
|
||||
VariadicMutableSingleton.prototype.reload = function () {
|
||||
var _a;
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
return (_a = this._Get_singleton(args)).reload.apply(_a, __spreadArray([], __read(args), false));
|
||||
};
|
||||
VariadicMutableSingleton.prototype.clear = function () {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
if (!(args.length === 0)) return [3 /*break*/, 1];
|
||||
this.dict_.clear();
|
||||
return [3 /*break*/, 3];
|
||||
case 1: return [4 /*yield*/, this._Get_singleton(args).clear()];
|
||||
case 2:
|
||||
_a.sent();
|
||||
_a.label = 3;
|
||||
case 3: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/* ---------------------------------------------------------------
|
||||
ACCESSORS
|
||||
--------------------------------------------------------------- */
|
||||
VariadicMutableSingleton.prototype.get = function () {
|
||||
var _a;
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
return (_a = this._Get_singleton(args)).get.apply(_a, __spreadArray([], __read(args), false));
|
||||
};
|
||||
VariadicMutableSingleton.prototype.is_loaded = function () {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
return this._Get_singleton(args).is_loaded();
|
||||
};
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
VariadicMutableSingleton.prototype._Get_singleton = function (args) {
|
||||
var it = this.dict_.find(args);
|
||||
if (it.equals(this.dict_.end()) === true)
|
||||
it = this.dict_.emplace(args, new MutableSingleton_1.MutableSingleton(this.closure_)).first;
|
||||
return it.second;
|
||||
};
|
||||
return VariadicMutableSingleton;
|
||||
}());
|
||||
exports.VariadicMutableSingleton = VariadicMutableSingleton;
|
||||
//# sourceMappingURL=VariadicMutableSingleton.js.map
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* Variadic singleton generator.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.comm/samchon
|
||||
*/
|
||||
export declare class VariadicSingleton<T, Args extends any[]> {
|
||||
private readonly closure_;
|
||||
private readonly dict_;
|
||||
constructor(closure: (...args: Args) => T, hashFunc?: (args: Args) => number, pred?: (x: Args, y: Args) => boolean);
|
||||
get(...args: Args): T;
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
"use strict";
|
||||
var __read = (this && this.__read) || function (o, n) {
|
||||
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
||||
if (!m) return o;
|
||||
var i = m.call(o), r, ar = [], e;
|
||||
try {
|
||||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
||||
}
|
||||
catch (error) { e = { error: error }; }
|
||||
finally {
|
||||
try {
|
||||
if (r && !r.done && (m = i["return"])) m.call(i);
|
||||
}
|
||||
finally { if (e) throw e.error; }
|
||||
}
|
||||
return ar;
|
||||
};
|
||||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
||||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
||||
if (ar || !(i in from)) {
|
||||
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
||||
ar[i] = from[i];
|
||||
}
|
||||
}
|
||||
return to.concat(ar || Array.prototype.slice.call(from));
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.VariadicSingleton = void 0;
|
||||
//================================================================
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
//================================================================
|
||||
var Singleton_1 = require("./Singleton");
|
||||
var HashMap_1 = require("../container/HashMap");
|
||||
var hash_1 = require("../functional/hash");
|
||||
var iterations_1 = require("../ranges/algorithm/iterations");
|
||||
/**
|
||||
* Variadic singleton generator.
|
||||
*
|
||||
* @author Jeongho Nam - https://github.comm/samchon
|
||||
*/
|
||||
var VariadicSingleton = /** @class */ (function () {
|
||||
function VariadicSingleton(closure, hashFunc, pred) {
|
||||
if (hashFunc === void 0) { hashFunc = function (args) { return hash_1.hash.apply(void 0, __spreadArray([], __read(args), false)); }; }
|
||||
if (pred === void 0) { pred = iterations_1.equal; }
|
||||
this.closure_ = closure;
|
||||
this.dict_ = new HashMap_1.HashMap(hashFunc, pred);
|
||||
}
|
||||
VariadicSingleton.prototype.get = function () {
|
||||
var _a;
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
var it = this.dict_.find(args);
|
||||
if (it.equals(this.dict_.end()) == true)
|
||||
it = this.dict_.emplace(args, new Singleton_1.Singleton(this.closure_)).first;
|
||||
return (_a = it.second).get.apply(_a, __spreadArray([], __read(args), false));
|
||||
};
|
||||
return VariadicSingleton;
|
||||
}());
|
||||
exports.VariadicSingleton = VariadicSingleton;
|
||||
//# sourceMappingURL=VariadicSingleton.js.map
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* Variadic timed singleton generator.
|
||||
*
|
||||
* The `VariadicTimedSingleton` is a type of {@link VariadicSingleton} class who re-constructs
|
||||
* the singleton value repeatedly whenever specific time has been elapsed after the last lazy
|
||||
* construction.
|
||||
*
|
||||
* @template T Type of the value to be lazy-constructed
|
||||
* @template Args Type of parameters of the lazy constructor function
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
export declare class VariadicTimedSingleton<T, Args extends any[]> {
|
||||
private readonly interval_;
|
||||
private readonly closure_;
|
||||
private readonly dict_;
|
||||
/**
|
||||
* Initializer Constructor.
|
||||
*
|
||||
* @param interval Specific interval time, to determine whether re-generation of the singleton value is required or not, as milliseconds
|
||||
* @param closure Lazy constructor function returning the target value
|
||||
* @param hasher Hash function for the *lazy constructor* function arguments
|
||||
* @param pred Predicator function for the *lazy constructor* function arguments
|
||||
*/
|
||||
constructor(interval: number, closure: (...args: Args) => T, hasher?: (args: Args) => number, pred?: (x: Args, y: Args) => boolean);
|
||||
/**
|
||||
* Get value.
|
||||
*
|
||||
* @param args Parameters for the lazy constructor function
|
||||
* @returns The lazy constructed value
|
||||
*/
|
||||
get(...args: Args): T;
|
||||
}
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
"use strict";
|
||||
var __read = (this && this.__read) || function (o, n) {
|
||||
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
||||
if (!m) return o;
|
||||
var i = m.call(o), r, ar = [], e;
|
||||
try {
|
||||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
||||
}
|
||||
catch (error) { e = { error: error }; }
|
||||
finally {
|
||||
try {
|
||||
if (r && !r.done && (m = i["return"])) m.call(i);
|
||||
}
|
||||
finally { if (e) throw e.error; }
|
||||
}
|
||||
return ar;
|
||||
};
|
||||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
||||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
||||
if (ar || !(i in from)) {
|
||||
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
||||
ar[i] = from[i];
|
||||
}
|
||||
}
|
||||
return to.concat(ar || Array.prototype.slice.call(from));
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.VariadicTimedSingleton = void 0;
|
||||
var HashMap_1 = require("../container/HashMap");
|
||||
var TimedSingleton_1 = require("./TimedSingleton");
|
||||
var iterations_1 = require("../ranges/algorithm/iterations");
|
||||
var hash_1 = require("../functional/hash");
|
||||
/**
|
||||
* Variadic timed singleton generator.
|
||||
*
|
||||
* The `VariadicTimedSingleton` is a type of {@link VariadicSingleton} class who re-constructs
|
||||
* the singleton value repeatedly whenever specific time has been elapsed after the last lazy
|
||||
* construction.
|
||||
*
|
||||
* @template T Type of the value to be lazy-constructed
|
||||
* @template Args Type of parameters of the lazy constructor function
|
||||
* @author Jeongho Nam - https://github.com/samchon
|
||||
*/
|
||||
var VariadicTimedSingleton = /** @class */ (function () {
|
||||
/**
|
||||
* Initializer Constructor.
|
||||
*
|
||||
* @param interval Specific interval time, to determine whether re-generation of the singleton value is required or not, as milliseconds
|
||||
* @param closure Lazy constructor function returning the target value
|
||||
* @param hasher Hash function for the *lazy constructor* function arguments
|
||||
* @param pred Predicator function for the *lazy constructor* function arguments
|
||||
*/
|
||||
function VariadicTimedSingleton(interval, closure, hasher, pred) {
|
||||
if (hasher === void 0) { hasher = function (args) { return hash_1.hash.apply(void 0, __spreadArray([], __read(args), false)); }; }
|
||||
if (pred === void 0) { pred = iterations_1.equal; }
|
||||
this.interval_ = interval;
|
||||
this.closure_ = closure;
|
||||
this.dict_ = new HashMap_1.HashMap(hasher, pred);
|
||||
}
|
||||
/**
|
||||
* Get value.
|
||||
*
|
||||
* @param args Parameters for the lazy constructor function
|
||||
* @returns The lazy constructed value
|
||||
*/
|
||||
VariadicTimedSingleton.prototype.get = function () {
|
||||
var _a;
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
var it = this.dict_.find(args);
|
||||
if (it.equals(this.dict_.end()) == true) {
|
||||
var singleton = new TimedSingleton_1.TimedSingleton(this.interval_, this.closure_);
|
||||
it = this.dict_.emplace(args, singleton).first;
|
||||
}
|
||||
return (_a = it.second).get.apply(_a, __spreadArray([], __read(args), false));
|
||||
};
|
||||
return VariadicTimedSingleton;
|
||||
}());
|
||||
exports.VariadicTimedSingleton = VariadicTimedSingleton;
|
||||
//# sourceMappingURL=VariadicTimedSingleton.js.map
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
import { ILockable } from "../base/thread/ILockable";
|
||||
/**
|
||||
* Sleep for time span.
|
||||
*
|
||||
* @param ms The milliseconds to sleep.
|
||||
*/
|
||||
export declare function sleep_for(ms: number): Promise<void>;
|
||||
/**
|
||||
* Sleep until time expiration.
|
||||
*
|
||||
* @param at The time point to wake up.
|
||||
*/
|
||||
export declare function sleep_until(at: Date): Promise<void>;
|
||||
/**
|
||||
* Lock multiple mutexes.
|
||||
*
|
||||
* @param items Items to lock.
|
||||
*/
|
||||
export declare function lock(...items: Pick<ILockable, "lock">[]): Promise<void>;
|
||||
/**
|
||||
* Try lock mutexes.
|
||||
*
|
||||
* @param items Items to try lock.
|
||||
* @return Index of mutex who failed to lock. None of them're failed, then returns `-1`.
|
||||
*/
|
||||
export declare function try_lock(...items: Pick<ILockable, "try_lock">[]): Promise<number>;
|
||||
-146
@@ -1,146 +0,0 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var __values = (this && this.__values) || function(o) {
|
||||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
||||
if (m) return m.call(o);
|
||||
if (o && typeof o.length === "number") return {
|
||||
next: function () {
|
||||
if (o && i >= o.length) o = void 0;
|
||||
return { value: o && o[i++], done: !o };
|
||||
}
|
||||
};
|
||||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.try_lock = exports.lock = exports.sleep_until = exports.sleep_for = void 0;
|
||||
/**
|
||||
* Sleep for time span.
|
||||
*
|
||||
* @param ms The milliseconds to sleep.
|
||||
*/
|
||||
function sleep_for(ms) {
|
||||
return new Promise(function (resolve) {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
exports.sleep_for = sleep_for;
|
||||
/**
|
||||
* Sleep until time expiration.
|
||||
*
|
||||
* @param at The time point to wake up.
|
||||
*/
|
||||
function sleep_until(at) {
|
||||
var now = new Date();
|
||||
var ms = at.getTime() - now.getTime(); // MILLISECONDS TO WAIT
|
||||
return sleep_for(ms); // CONVERT TO THE SLEEP_FOR
|
||||
}
|
||||
exports.sleep_until = sleep_until;
|
||||
/**
|
||||
* Lock multiple mutexes.
|
||||
*
|
||||
* @param items Items to lock.
|
||||
*/
|
||||
function lock() {
|
||||
var items = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
items[_i] = arguments[_i];
|
||||
}
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var promises, items_1, items_1_1, mtx;
|
||||
var e_1, _a;
|
||||
return __generator(this, function (_b) {
|
||||
switch (_b.label) {
|
||||
case 0:
|
||||
promises = [];
|
||||
try {
|
||||
for (items_1 = __values(items), items_1_1 = items_1.next(); !items_1_1.done; items_1_1 = items_1.next()) {
|
||||
mtx = items_1_1.value;
|
||||
promises.push(mtx.lock());
|
||||
}
|
||||
}
|
||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (items_1_1 && !items_1_1.done && (_a = items_1.return)) _a.call(items_1);
|
||||
}
|
||||
finally { if (e_1) throw e_1.error; }
|
||||
}
|
||||
return [4 /*yield*/, Promise.all(promises)];
|
||||
case 1:
|
||||
_b.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.lock = lock;
|
||||
/**
|
||||
* Try lock mutexes.
|
||||
*
|
||||
* @param items Items to try lock.
|
||||
* @return Index of mutex who failed to lock. None of them're failed, then returns `-1`.
|
||||
*/
|
||||
function try_lock() {
|
||||
var items = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
items[_i] = arguments[_i];
|
||||
}
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var i;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
i = 0;
|
||||
_a.label = 1;
|
||||
case 1:
|
||||
if (!(i < items.length)) return [3 /*break*/, 4];
|
||||
return [4 /*yield*/, items[i].try_lock()];
|
||||
case 2:
|
||||
if ((_a.sent()) === false)
|
||||
return [2 /*return*/, i];
|
||||
_a.label = 3;
|
||||
case 3:
|
||||
++i;
|
||||
return [3 /*break*/, 1];
|
||||
case 4: return [2 /*return*/, -1];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.try_lock = try_lock;
|
||||
//# sourceMappingURL=global.js.map
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
export * from "./Mutex";
|
||||
export * from "./TimedMutex";
|
||||
export * from "./SharedMutex";
|
||||
export * from "./SharedTimedMutex";
|
||||
export * from "./ConditionVariable";
|
||||
export * from "./UniqueLock";
|
||||
export * from "./SharedLock";
|
||||
export * from "./Semaphore";
|
||||
export * from "./Latch";
|
||||
export * from "./Barrier";
|
||||
export * from "./MutableSingleton";
|
||||
export * from "./TimedSingleton";
|
||||
export * from "./VariadicMutableSingleton";
|
||||
export * from "./VariadicTimedSingleton";
|
||||
export * from "./VariadicSingleton";
|
||||
export * from "./Singleton";
|
||||
export * from "./global";
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//================================================================
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module std
|
||||
*/
|
||||
//================================================================
|
||||
__exportStar(require("./Mutex"), exports);
|
||||
__exportStar(require("./TimedMutex"), exports);
|
||||
__exportStar(require("./SharedMutex"), exports);
|
||||
__exportStar(require("./SharedTimedMutex"), exports);
|
||||
__exportStar(require("./ConditionVariable"), exports);
|
||||
__exportStar(require("./UniqueLock"), exports);
|
||||
__exportStar(require("./SharedLock"), exports);
|
||||
__exportStar(require("./Semaphore"), exports);
|
||||
__exportStar(require("./Latch"), exports);
|
||||
__exportStar(require("./Barrier"), exports);
|
||||
__exportStar(require("./MutableSingleton"), exports);
|
||||
__exportStar(require("./TimedSingleton"), exports);
|
||||
__exportStar(require("./VariadicMutableSingleton"), exports);
|
||||
__exportStar(require("./VariadicTimedSingleton"), exports);
|
||||
__exportStar(require("./VariadicSingleton"), exports);
|
||||
__exportStar(require("./Singleton"), exports);
|
||||
__exportStar(require("./global"), exports);
|
||||
//# sourceMappingURL=index.js.map
|
||||
Reference in New Issue
Block a user