63 lines
1.8 KiB
JavaScript
63 lines
1.8 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Mutex = void 0;
|
|
const Array_1 = require("./Array");
|
|
const Deferred_1 = require("./Deferred");
|
|
/**
|
|
* Aggregate promises efficiently
|
|
*/
|
|
class Mutex {
|
|
constructor() {
|
|
this._pushCount = 0;
|
|
this._arr = [];
|
|
}
|
|
get arr() {
|
|
(0, Array_1.filterInPlace)(this._arr, (ea) => ea.pending);
|
|
return this._arr;
|
|
}
|
|
get pushCount() {
|
|
return this._pushCount;
|
|
}
|
|
push(f) {
|
|
this._pushCount++;
|
|
const p = f();
|
|
// Don't cause awaitAll to die if a task rejects:
|
|
this.arr.push(new Deferred_1.Deferred().observeQuietly(p));
|
|
return p;
|
|
}
|
|
/**
|
|
* Run f() after all prior-enqueued promises have resolved.
|
|
*/
|
|
serial(f) {
|
|
return this.push(() => this.awaitAll().then(() => f()));
|
|
}
|
|
/**
|
|
* Only run f() if all prior have finished, otherwise, no-op and wait until
|
|
* all pending have resolved.
|
|
*/
|
|
runIfIdle(f) {
|
|
return this.pending ? undefined : this.serial(f);
|
|
}
|
|
get pendingCount() {
|
|
// Don't need vacuuming, so we can use this._arr:
|
|
return this._arr.reduce((sum, ea) => sum + (ea.pending ? 1 : 0), 0);
|
|
}
|
|
get pending() {
|
|
return this.pendingCount > 0;
|
|
}
|
|
get settled() {
|
|
// this.arr is a getter that does vacuuming
|
|
return this.arr.length === 0;
|
|
}
|
|
/**
|
|
* @return a promise that will be resolved when all previously-pushed Promises
|
|
* are resolved. Any promise rejection will throw the whole chain.
|
|
*/
|
|
awaitAll() {
|
|
return this.arr.length === 0
|
|
? Promise.resolve(undefined)
|
|
: Promise.all(this.arr.map((ea) => ea.promise)).then(() => undefined);
|
|
}
|
|
}
|
|
exports.Mutex = Mutex;
|
|
//# sourceMappingURL=Mutex.js.map
|