mix-async-generator
Version:
``` npm i mix-async-generator ```
225 lines • 28.9 kB
JavaScript
import { Evt } from "evt";
import { safePromiseThen, PromiseOut } from "@bfchain/util-extends-promise";
import { FastQuene } from "./FastQuene";
const DONE = Promise.resolve({
step: { value: undefined, done: true },
});
export class MixAsyncGenerator {
constructor() {
this._allGenList = new FastQuene();
/**正在执行中的任务,等待返回后就从这个集合中移除 */
this._runnings = new Map();
/**候补队列 */
this._benchGen = new FastQuene();
/**自由队列 */
this._freeGen = new FastQuene();
this._genWaitter = new FastQuene();
// private _traceCount = 0;
this._freeResult = new FastQuene();
this._benchResult = new FastQuene();
this._resultWaiter = new FastQuene();
this.onError = new Evt();
}
join(runner, opts) {
let bench = false;
let jumpGun;
let name = `gen-${this._allGenList.size + 1}`;
if (opts !== undefined) {
opts.name !== undefined && (name = opts.name);
opts.bench !== undefined && (bench = opts.bench);
jumpGun = opts.jumpGun;
}
if (jumpGun === undefined) {
jumpGun = bench ? 1 : 1; /**非惰性元素至少抢跑1步 */
}
if (bench === false && jumpGun < 1) {
throw new RangeError("when runner no in bench, jump gun should not be 0");
}
return this._join({
runner,
name,
bench,
jumpGun,
currentStep: undefined,
inQueueSteps: 0,
});
}
_join(gen) {
this._allGenList.push(gen);
/// 否则保存到惰性列表中,需要时再使用
if (gen.bench) {
this._benchGen.push(gen);
}
/// 如果是非惰性的,那么直接启动迭代
else {
this._handleGen(gen);
}
return gen;
}
remove(gen) {
if (this._allGenList.remove(gen)) {
/// 如果全部归空了,那么将其余在等待中的都关闭掉
if (this._allGenList.size === 0) {
do {
const waiter = this._resultWaiter.shift();
if (waiter === undefined) {
break;
}
waiter.resolve(DONE);
} while (true);
}
return true;
}
return false;
}
_enqueueGen(gen) {
// 是否有在等待中的
const waiter = this._genWaitter.shift();
if (waiter) {
waiter.resolve(gen);
}
/// 如果是惰性元素,那么回到惰性队列
else if (gen.bench) {
this._benchGen.push(gen);
}
/// 如果是非惰性元素,那么回到自由队列
else {
this._freeGen.push(gen);
}
}
async _dequeueGen() {
// 获取一个可用的迭代器
const gen = this._freeGen.shift() ||
this._benchGen.shift() ||
(await this._genWaitter.push(new PromiseOut()).promise);
this._handleGen(gen);
}
_handleGen(gen) {
const item = gen.runner.next();
this._runnings.set(item, gen);
// 如果完成,则回到自由队列
safePromiseThen(item, (value) => {
this._runnings.delete(item);
// 缓存当前结果
gen.currentStep = value;
/// 如果已经完结了,那么直接移除掉了
if (value.done) {
this.remove(gen);
/// 如果没有任何在执行中的元素,就需要继续从队列中读取出来执行,否则外面的Promise就永远无法resolve
if (this._runnings.size === 0) {
this._dequeueGen();
}
}
/// 否则回到队列中继续提供下一个迭代
else {
// 传递到结果队列中
this._enqueueResult({ from: gen, step: value });
/// 如果可以偷跑,那么继续执行
if (gen.inQueueSteps < gen.jumpGun) {
this._handleGen(gen);
}
else {
// 回到空闲队列中
this._enqueueGen(gen);
}
}
}, (reason) => {
this._runnings.delete(item);
// 如果已经出错,那么直接移除
this.remove(gen);
// 向外传递错误
this.onError.post({ from: gen, reason });
});
}
/**入列
* 这个函数与_handleGen是紧密关联的,是_handleGen的一部分
*/
_enqueueResult(result) {
/// 是否有在等待中的
const waiter = this._resultWaiter.shift();
if (waiter !== undefined) {
/**
* 因为本就是要直接返回的,所以这里直接将步数减去
*
* Waiter模式不需要修改inQueueSteps,因为是预约的,直接返回
*/
waiter.resolve(result);
}
else {
result.from.bench
? this._benchResult.push(result)
: this._freeResult.push(result);
result.from.inQueueSteps += 1;
}
}
/**出列 */
_dequeueResult() {
/// 再从结果队列中读取
const resultWithFrom1 = this._freeResult.shift();
if (resultWithFrom1 !== undefined) {
const gen = resultWithFrom1.from;
gen.inQueueSteps -= 1;
if (this._freeGen.remove(gen)) {
this._handleGen(gen);
}
return resultWithFrom1;
}
const resultWithFrom2 = this._benchResult.shift();
if (resultWithFrom2 !== undefined) {
const gen = resultWithFrom2.from;
gen.inQueueSteps -= 1;
if (this._benchGen.remove(gen)) {
this._handleGen(gen);
}
/**
* @TODO 使用了候补元素,那么就要对元素尽快进行补充
*/
return resultWithFrom2;
}
// 否则排队进行等待,Waiter模式不需要修改inQueueSteps,因为是预约的,直接返回
const resultPromise = this._resultWaiter.push(new PromiseOut()).promise;
/// 必要时,让选手出列
if (
// 如果没有任何一个在运行中的任务:那么立刻执行
this._runnings.size === 0 ||
// 如果自由队列为空,但是候补队列有存在的:那么也立刻执行
(this._freeGen.size === 0 && this._benchGen.size !== 0)) {
this._dequeueGen();
}
// console.log(++this._traceCount);
// if (this._traceCount === 2) {
// debugger;
// }
return resultPromise;
}
next() {
if (this.isDone) {
return DONE;
}
return this._dequeueResult();
}
get isDone() {
return (
/* _allGenList为空也就意味着_running为空 */ this._allGenList.size === 0 &&
this._freeResult.size === 0 &&
this._benchResult.size === 0);
}
async *toAsyncIterator() {
while (true) {
const result = await this.next();
if (result.step.done) {
return;
}
yield result.step.value;
}
}
async toPromise() {
while (true) {
const result = await this.next();
if (result.step.done) {
return;
}
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWl4QXN5bmNHZW5lcmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvTWl4QXN5bmNHZW5lcmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUMxQixPQUFPLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzVFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUF1Q3hDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUM7SUFDM0IsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsSUFBYSxFQUFFO0NBQ2hELENBQUMsQ0FBQztBQUVILE1BQU0sT0FBTyxpQkFBaUI7SUFBOUI7UUFHVSxnQkFBVyxHQUFHLElBQUksU0FBUyxFQUE0QixDQUFDO1FBZ0ZoRSw2QkFBNkI7UUFDckIsY0FBUyxHQUFHLElBQUksR0FBRyxFQUd4QixDQUFDO1FBNENKLFVBQVU7UUFDRixjQUFTLEdBQUcsSUFBSSxTQUFTLEVBQWtDLENBQUM7UUFDcEUsVUFBVTtRQUNGLGFBQVEsR0FBRyxJQUFJLFNBQVMsRUFBbUMsQ0FBQztRQUM1RCxnQkFBVyxHQUFHLElBQUksU0FBUyxFQUF3QyxDQUFDO1FBb0U1RSwyQkFBMkI7UUFDbkIsZ0JBQVcsR0FBRyxJQUFJLFNBQVMsRUFFaEMsQ0FBQztRQUNJLGlCQUFZLEdBQUcsSUFBSSxTQUFTLEVBRWpDLENBQUM7UUFDSSxrQkFBYSxHQUFHLElBQUksU0FBUyxFQUVsQyxDQUFDO1FBQ0ssWUFBTyxHQUFHLElBQUksR0FBRyxFQUE4QixDQUFDO0lBK0IzRCxDQUFDO0lBaFBDLElBQUksQ0FDRixNQUF3QyxFQUN4QyxJQUEyRDtRQUUzRCxJQUFJLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDbEIsSUFBSSxPQUEyQixDQUFDO1FBQ2hDLElBQUks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QyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksS0FBSyxDQUFDO1lBQzlELElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxLQUFLLENBQUM7WUFDM0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUM3QixDQUFDO0lBQ0osQ0FBQztJQUNELEtBQUssQ0FBQyxDQUFDLGVBQWU7UUFDcEIsT0FBTyxJQUFJLEVBQUU7WUFDWCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNqQyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFO2dCQUNwQixPQUFPO2FBQ1I7WUFDRCxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO1NBQ3pCO0lBQ0gsQ0FBQztJQUNELEtBQUssQ0FBQyxTQUFTO1FBQ2IsT0FBTyxJQUFJLEVBQUU7WUFDWCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNqQyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFO2dCQUNwQixPQUFPO2FBQ1I7U0FDRjtJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEV2dCB9IGZyb20gXCJldnRcIjtcclxuaW1wb3J0IHsgc2FmZVByb21pc2VUaGVuLCBQcm9taXNlT3V0IH0gZnJvbSBcIkBiZmNoYWluL3V0aWwtZXh0ZW5kcy1wcm9taXNlXCI7XHJcbmltcG9ydCB7IEZhc3RRdWVuZSB9IGZyb20gXCIuL0Zhc3RRdWVuZVwiO1xyXG5cclxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIE1peEFzeW5jR2VuZXJhdG9yIHtcclxuICB0eXBlIEFHPE5leHRPdXQgPSB1bmtub3duLCBSZXR1cm4gPSB1bmtub3duLCBOZXh0SW4gPSB1bmtub3duPiA9IFtcclxuICAgIE5leHRPdXQsXHJcbiAgICBSZXR1cm4sXHJcbiAgICBOZXh0SW5cclxuICBdO1xyXG4gIHR5cGUgR2VuPFQgZXh0ZW5kcyBBRywgQiBleHRlbmRzIGJvb2xlYW4gPSBib29sZWFuPiA9IHtcclxuICAgIG5hbWU6IHN0cmluZztcclxuICAgIHJ1bm5lcjogQXN5bmNHZW5lcmF0b3I8VFswXSwgVFsxXSwgVFsyXT47XHJcbiAgICAvKirmm7/ooaXlhYPntKAv5oOw5oCn5YWD57SgXHJcbiAgICAgKiDmhI/lkbPnnYDlj6rmnInliLDkuI3lvpfkuI3nlKjnmoTml7blgJnmiY3kvJrljrvkvb/nlKhcclxuICAgICAqL1xyXG4gICAgYmVuY2g6IEI7XHJcbiAgICAvKirlvZPliY3nmoTmraXkvJAgKi9cclxuICAgIGN1cnJlbnRTdGVwOiBJdGVyYXRvclJlc3VsdDxUWzBdLCBUWzFdPiB8IHVuZGVmaW5lZDtcclxuICAgIC8qKuWBt+i3keeahOatpeaVsO+8jOm7mOiupOaYrzBcclxuICAgICAqIOWBt+i3keaEj+WRs+edgOWug+Wni+e7iOS8muWKquWKm+aPkOS+m2p1bXBHdW7kuKpyZXN1bHRcclxuICAgICAqIOabv+ihpeWFg+e0oOS5n+WPr+S7peWBt+i3ke+8jOS9huWPquaciei9ruWIsOWug+S4iuWcuuaJjeiDveWBt+i3kVxyXG4gICAgICovXHJcbiAgICBqdW1wR3VuOiBudW1iZXI7XHJcbiAgICAvKirnvJPlrZjlnKjpmJ/liJfkuK3nmoTmraXkvJDmlbAgKi9cclxuICAgIGluUXVldWVTdGVwczogbnVtYmVyO1xyXG4gIH07XHJcbiAgdHlwZSBSZXN1bHQ8VCBleHRlbmRzIEFHPiA9IHtcclxuICAgIHN0ZXA6IEl0ZXJhdG9yUmVzdWx0PFRbMF0sIFRbMV0+O1xyXG4gICAgZnJvbT86IEdlbjxUPjtcclxuICB9O1xyXG4gIHR5cGUgUmVzdWx0V2l0aEZyb208VCBleHRlbmRzIEFHLCBCIGV4dGVuZHMgYm9vbGVhbiA9IGJvb2xlYW4+ID0ge1xyXG4gICAgc3RlcDogSXRlcmF0b3JSZXN1bHQ8VFswXSwgVFsxXT47XHJcbiAgICBmcm9tOiBHZW48VCwgQj47XHJcbiAgfTtcclxuICB0eXBlIEVycm9yPFQgZXh0ZW5kcyBBRz4gPSB7XHJcbiAgICBmcm9tOiBHZW48VD47XHJcbiAgICByZWFzb246IHVua25vd247XHJcbiAgfTtcclxufVxyXG5cclxuY29uc3QgRE9ORSA9IFByb21pc2UucmVzb2x2ZSh7XHJcbiAgc3RlcDogeyB2YWx1ZTogdW5kZWZpbmVkLCBkb25lOiB0cnVlIGFzIGNvbnN0IH0sXHJcbn0pO1xyXG5cclxuZXhwb3J0IGNsYXNzIE1peEFzeW5jR2VuZXJhdG9yPFxyXG4gIFQgZXh0ZW5kcyBNaXhBc3luY0dlbmVyYXRvci5BRyA9IE1peEFzeW5jR2VuZXJhdG9yLkFHXHJcbj4ge1xyXG4gIHByaXZhdGUgX2FsbEdlbkxpc3QgPSBuZXcgRmFzdFF1ZW5lPE1peEFzeW5jR2VuZXJhdG9yLkdlbjxUPj4oKTtcclxuICBqb2luKFxyXG4gICAgcnVubmVyOiBBc3luY0dlbmVyYXRvcjxUWzBdLCBUWzFdLCBUWzJdPixcclxuICAgIG9wdHM/OiB7IG5hbWU/OiBzdHJpbmc7IGJlbmNoPzogYm9vbGVhbjsganVtcEd1bj86IG51bWJlciB9XHJcbiAgKSB7XHJcbiAgICBsZXQgYmVuY2ggPSBmYWxzZTtcclxuICAgIGxldCBqdW1wR3VuOiBudW1iZXIgfCB1bmRlZmluZWQ7XHJcbiAgICBsZXQgbmFtZSA9IGBnZW4tJHt0aGlzLl9hbGxHZW5MaXN0LnNpemUgKyAxfWA7XHJcbiAgICBpZiAob3B0cyAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIG9wdHMubmFtZSAhPT0gdW5kZWZpbmVkICYmIChuYW1lID0gb3B0cy5uYW1lKTtcclxuICAgICAgb3B0cy5iZW5jaCAhPT0gdW5kZWZpbmVkICYmIChiZW5jaCA9IG9wdHMuYmVuY2gpO1xyXG4gICAgICBqdW1wR3VuID0gb3B0cy5qdW1wR3VuO1xyXG4gICAgfVxyXG4gICAgaWYgKGp1bXBHdW4gPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICBqdW1wR3VuID0gYmVuY2ggPyAxIDogMTsgLyoq6Z2e5oOw5oCn5YWD57Sg6Iez5bCR5oqi6LeRMeatpSAqL1xyXG4gICAgfVxyXG4gICAgaWYgKGJlbmNoID09PSBmYWxzZSAmJiBqdW1wR3VuIDwgMSkge1xyXG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIndoZW4gcnVubmVyIG5vIGluIGJlbmNoLCBqdW1wIGd1biBzaG91bGQgbm90IGJlIDBcIik7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuX2pvaW4oe1xyXG4gICAgICBydW5uZXIsXHJcbiAgICAgIG5hbWUsXHJcbiAgICAgIGJlbmNoLFxyXG4gICAgICBqdW1wR3VuLFxyXG4gICAgICBjdXJyZW50U3RlcDogdW5kZWZpbmVkLFxyXG4gICAgICBpblF1ZXVlU3RlcHM6IDAsXHJcbiAgICB9KTtcclxuICB9XHJcbiAgcHJpdmF0ZSBfam9pbihnZW46IE1peEFzeW5jR2VuZXJhdG9yLkdlbjxUPikge1xyXG4gICAgdGhpcy5fYWxsR2VuTGlzdC5wdXNoKGdlbik7XHJcbiAgICAvLy8g5ZCm5YiZ5L+d5a2Y5Yiw5oOw5oCn5YiX6KGo5Lit77yM6ZyA6KaB5pe25YaN5L2/55SoXHJcbiAgICBpZiAoZ2VuLmJlbmNoKSB7XHJcbiAgICAgIHRoaXMuX2JlbmNoR2VuLnB1c2goZ2VuIGFzIE1peEFzeW5jR2VuZXJhdG9yLkdlbjxULCB0cnVlPik7XHJcbiAgICB9XHJcbiAgICAvLy8g5aaC5p6c5piv6Z2e5oOw5oCn55qE77yM6YKj5LmI55u05o6l5ZCv5Yqo6L+t5LujXHJcbiAgICBlbHNlIHtcclxuICAgICAgdGhpcy5faGFuZGxlR2VuKGdlbik7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZ2VuO1xyXG4gIH1cclxuICByZW1vdmUoZ2VuOiBNaXhBc3luY0dlbmVyYXRvci5HZW48VD4pIHtcclxuICAgIGlmICh0aGlzLl9hbGxHZW5MaXN0LnJlbW92ZShnZW4pKSB7XHJcbiAgICAgIC8vLyDlpoLmnpzlhajpg6jlvZLnqbrkuobvvIzpgqPkuYjlsIblhbbkvZnlnKjnrYnlvoXkuK3nmoTpg73lhbPpl63mjolcclxuICAgICAgaWYgKHRoaXMuX2FsbEdlbkxpc3Quc2l6ZSA9PT0gMCkge1xyXG4gICAgICAgIGRvIHtcclxuICAgICAgICAgIGNvbnN0IHdhaXRlciA9IHRoaXMuX3Jlc3VsdFdhaXRlci5zaGlmdCgpO1xyXG4gICAgICAgICAgaWYgKHdhaXRlciA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgd2FpdGVyLnJlc29sdmUoRE9ORSk7XHJcbiAgICAgICAgfSB3aGlsZSAodHJ1ZSk7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG4gIHByaXZhdGUgX2VucXVldWVHZW4oZ2VuOiBNaXhBc3luY0dlbmVyYXRvci5HZW48VD4pIHtcclxuICAgIC8vIOaYr+WQpuacieWcqOetieW+heS4reeahFxyXG4gICAgY29uc3Qgd2FpdGVyID0gdGhpcy5fZ2VuV2FpdHRlci5zaGlmdCgpO1xyXG4gICAgaWYgKHdhaXRlcikge1xyXG4gICAgICB3YWl0ZXIucmVzb2x2ZShnZW4pO1xyXG4gICAgfVxyXG4gICAgLy8vIOWmguaenOaYr+aDsOaAp+WFg+e0oO+8jOmCo+S5iOWbnuWIsOaDsOaAp+mYn+WIl1xyXG4gICAgZWxzZSBpZiAoZ2VuLmJlbmNoKSB7XHJcbiAgICAgIHRoaXMuX2JlbmNoR2VuLnB1c2goZ2VuIGFzIE1peEFzeW5jR2VuZXJhdG9yLkdlbjxULCB0cnVlPik7XHJcbiAgICB9XHJcbiAgICAvLy8g5aaC5p6c5piv6Z2e5oOw5oCn5YWD57Sg77yM6YKj5LmI5Zue5Yiw6Ieq55Sx6Zif5YiXXHJcbiAgICBlbHNlIHtcclxuICAgICAgdGhpcy5fZnJlZUdlbi5wdXNoKGdlbiBhcyBNaXhBc3luY0dlbmVyYXRvci5HZW48VCwgZmFsc2U+KTtcclxuICAgIH1cclxuICB9XHJcbiAgcHJpdmF0ZSBhc3luYyBfZGVxdWV1ZUdlbigpIHtcclxuICAgIC8vIOiOt+WPluS4gOS4quWPr+eUqOeahOi/reS7o+WZqFxyXG4gICAgY29uc3QgZ2VuID1cclxuICAgICAgdGhpcy5fZnJlZUdlbi5zaGlmdCgpIHx8XHJcbiAgICAgIHRoaXMuX2JlbmNoR2VuLnNoaWZ0KCkgfHxcclxuICAgICAgKGF3YWl0IHRoaXMuX2dlbldhaXR0ZXIucHVzaChuZXcgUHJvbWlzZU91dCgpKS5wcm9taXNlKTtcclxuICAgIHRoaXMuX2hhbmRsZUdlbihnZW4pO1xyXG4gIH1cclxuICAvKirmraPlnKjmiafooYzkuK3nmoTku7vliqHvvIznrYnlvoXov5Tlm57lkI7lsLHku47ov5nkuKrpm4blkIjkuK3np7vpmaQgKi9cclxuICBwcml2YXRlIF9ydW5uaW5ncyA9IG5ldyBNYXA8XHJcbiAgICBQcm9taXNlPEl0ZXJhdG9yUmVzdWx0PFRbMF0sIFRbMV0+PixcclxuICAgIE1peEFzeW5jR2VuZXJhdG9yLkdlbjxUPlxyXG4gID4oKTtcclxuICBwcml2YXRlIF9oYW5kbGVHZW4oZ2VuOiBNaXhBc3luY0dlbmVyYXRvci5HZW48VD4pIHtcclxuICAgIGNvbnN0IGl0ZW0gPSBnZW4ucnVubmVyLm5leHQoKTtcclxuICAgIHRoaXMuX3J1bm5pbmdzLnNldChpdGVtLCBnZW4pO1xyXG4gICAgLy8g5aaC5p6c5a6M5oiQ77yM5YiZ5Zue5Yiw6Ieq55Sx6Zif5YiXXHJcbiAgICBzYWZlUHJvbWlzZVRoZW4oXHJcbiAgICAgIGl0ZW0sXHJcbiAgICAgICh2YWx1ZSkgPT4ge1xyXG4gICAgICAgIHRoaXMuX3J1bm5pbmdzLmRlbGV0ZShpdGVtKTtcclxuICAgICAgICAvLyDnvJPlrZjlvZPliY3nu5PmnpxcclxuICAgICAgICBnZW4uY3VycmVudFN0ZXAgPSB2YWx1ZTtcclxuICAgICAgICAvLy8g5aaC5p6c5bey57uP5a6M57uT5LqG77yM6YKj5LmI55u05o6l56e76Zmk5o6J5LqGXHJcbiAgICAgICAgaWYgKHZhbHVlLmRvbmUpIHtcclxuICAgICAgICAgIHRoaXMucmVtb3ZlKGdlbik7XHJcblxyXG4gICAgICAgICAgLy8vIOWmguaenOayoeacieS7u+S9leWcqOaJp+ihjOS4reeahOWFg+e0oO+8jOWwsemcgOimgee7p+e7reS7jumYn+WIl+S4reivu+WPluWHuuadpeaJp+ihjO+8jOWQpuWImeWklumdoueahFByb21pc2XlsLHmsLjov5zml6Dms5VyZXNvbHZlXHJcbiAgICAgICAgICBpZiAodGhpcy5fcnVubmluZ3Muc2l6ZSA9PT0gMCkge1xyXG4gICAgICAgICAgICB0aGlzLl9kZXF1ZXVlR2VuKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vLyDlkKbliJnlm57liLDpmJ/liJfkuK3nu6fnu63mj5DkvpvkuIvkuIDkuKrov63ku6NcclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgIC8vIOS8oOmAkuWIsOe7k+aenOmYn+WIl+S4rVxyXG4gICAgICAgICAgdGhpcy5fZW5xdWV1ZVJlc3VsdCh7IGZyb206IGdlbiwgc3RlcDogdmFsdWUgfSk7XHJcblxyXG4gICAgICAgICAgLy8vIOWmguaenOWPr+S7peWBt+i3ke+8jOmCo+S5iOe7p+e7reaJp+ihjFxyXG4gICAgICAgICAgaWYgKGdlbi5pblF1ZXVlU3RlcHMgPCBnZW4uanVtcEd1bikge1xyXG4gICAgICAgICAgICB0aGlzLl9oYW5kbGVHZW4oZ2VuKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIOWbnuWIsOepuumXsumYn+WIl+S4rVxyXG4gICAgICAgICAgICB0aGlzLl9lbnF1ZXVlR2VuKGdlbik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9LFxyXG4gICAgICAocmVhc29uOiB1bmtub3duKSA9PiB7XHJcbiAgICAgICAgdGhpcy5fcnVubmluZ3MuZGVsZXRlKGl0ZW0pO1xyXG4gICAgICAgIC8vIOWmguaenOW3sue7j+WHuumUme+8jOmCo+S5iOebtOaOpeenu+mZpFxyXG4gICAgICAgIHRoaXMucmVtb3ZlKGdlbik7XHJcbiAgICAgICAgLy8g5ZCR5aSW5Lyg6YCS6ZSZ6K+vXHJcbiAgICAgICAgdGhpcy5vbkVycm9yLnBvc3QoeyBmcm9tOiBnZW4sIHJlYXNvbiB9KTtcclxuICAgICAgfVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKuWAmeihpemYn+WIlyAqL1xyXG4gIHByaXZhdGUgX2JlbmNoR2VuID0gbmV3IEZhc3RRdWVuZTxNaXhBc3luY0dlbmVyYXRvci5HZW48VCwgdHJ1ZT4+KCk7XHJcbiAgLyoq6Ieq55Sx6Zif5YiXICovXHJcbiAgcHJpdmF0ZSBfZnJlZUdlbiA9IG5ldyBGYXN0UXVlbmU8TWl4QXN5bmNHZW5lcmF0b3IuR2VuPFQsIGZhbHNlPj4oKTtcclxuICBwcml2YXRlIF9nZW5XYWl0dGVyID0gbmV3IEZhc3RRdWVuZTxQcm9taXNlT3V0PE1peEFzeW5jR2VuZXJhdG9yLkdlbjxUPj4+KCk7XHJcbiAgLyoq5YWl5YiXXHJcbiAgICog6L+Z5Liq5Ye95pWw5LiOX2hhbmRsZUdlbuaYr+e0p+WvhuWFs+iBlOeahO+8jOaYr19oYW5kbGVHZW7nmoTkuIDpg6jliIZcclxuICAgKi9cclxuICBwcml2YXRlIF9lbnF1ZXVlUmVzdWx0KHJlc3VsdDogTWl4QXN5bmNHZW5lcmF0b3IuUmVzdWx0V2l0aEZyb208VD4pIHtcclxuICAgIC8vLyDmmK/lkKbmnInlnKjnrYnlvoXkuK3nmoRcclxuICAgIGNvbnN0IHdhaXRlciA9IHRoaXMuX3Jlc3VsdFdhaXRlci5zaGlmdCgpO1xyXG4gICAgaWYgKHdhaXRlciAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIC8qKlxyXG4gICAgICAgKiDlm6DkuLrmnKzlsLHmmK/opoHnm7TmjqXov5Tlm57nmoTvvIzmiYDku6Xov5nph4znm7TmjqXlsIbmraXmlbDlh4/ljrtcclxuICAgICAgICpcclxuICAgICAgICogV2FpdGVy5qih5byP5LiN6ZyA6KaB5L+u5pS5aW5RdWV1ZVN0ZXBz77yM5Zug5Li65piv6aKE57qm55qE77yM55u05o6l6L+U5ZueXHJcbiAgICAgICAqL1xyXG4gICAgICB3YWl0ZXIucmVzb2x2ZShyZXN1bHQpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmVzdWx0LmZyb20uYmVuY2hcclxuICAgICAgICA/IHRoaXMuX2JlbmNoUmVzdWx0LnB1c2goXHJcbiAgICAgICAgICAgIHJlc3VsdCBhcyBNaXhBc3luY0dlbmVyYXRvci5SZXN1bHRXaXRoRnJvbTxULCB0cnVlPlxyXG4gICAgICAgICAgKVxyXG4gICAgICAgIDogdGhpcy5fZnJlZVJlc3VsdC5wdXNoKFxyXG4gICAgICAgICAgICByZXN1bHQgYXMgTWl4QXN5bmNHZW5lcmF0b3IuUmVzdWx0V2l0aEZyb208VCwgZmFsc2U+XHJcbiAgICAgICAgICApO1xyXG4gICAgICByZXN1bHQuZnJvbS5pblF1ZXVlU3RlcHMgKz0gMTtcclxuICAgIH1cclxuICB9XHJcbiAgLyoq5Ye65YiXICovXHJcbiAgcHJpdmF0ZSBfZGVxdWV1ZVJlc3VsdCgpIHtcclxuICAgIC8vLyDlho3ku47nu5PmnpzpmJ/liJfkuK3or7vlj5ZcclxuICAgIGNvbnN0IHJlc3VsdFdpdGhGcm9tMSA9IHRoaXMuX2ZyZWVSZXN1bHQuc2hpZnQoKTtcclxuICAgIGlmIChyZXN1bHRXaXRoRnJvbTEgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICBjb25zdCBnZW4gPSByZXN1bHRXaXRoRnJvbTEuZnJvbTtcclxuICAgICAgZ2VuLmluUXVldWVTdGVwcyAtPSAxO1xyXG4gICAgICBpZiAodGhpcy5fZnJlZUdlbi5yZW1vdmUoZ2VuKSkge1xyXG4gICAgICAgIHRoaXMuX2hhbmRsZUdlbihnZW4pO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiByZXN1bHRXaXRoRnJvbTE7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgcmVzdWx0V2l0aEZyb20yID0gdGhpcy5fYmVuY2hSZXN1bHQuc2hpZnQoKTtcclxuICAgIGlmIChyZXN1bHRXaXRoRnJvbTIgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICBjb25zdCBnZW4gPSByZXN1bHRXaXRoRnJvbTIuZnJvbTtcclxuICAgICAgZ2VuLmluUXVldWVTdGVwcyAtPSAxO1xyXG4gICAgICBpZiAodGhpcy5fYmVuY2hHZW4ucmVtb3ZlKGdlbikpIHtcclxuICAgICAgICB0aGlzLl9oYW5kbGVHZW4oZ2VuKTtcclxuICAgICAgfVxyXG4gICAgICAvKipcclxuICAgICAgICogQFRPRE8g5L2/55So5LqG5YCZ6KGl5YWD57Sg77yM6YKj5LmI5bCx6KaB5a+55YWD57Sg5bC95b+r6L+b6KGM6KGl5YWFXHJcbiAgICAgICAqL1xyXG4gICAgICByZXR1cm4gcmVzdWx0V2l0aEZyb20yO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIOWQpuWImeaOkumYn+i/m+ihjOetieW+he+8jFdhaXRlcuaooeW8j+S4jemcgOimgeS/ruaUuWluUXVldWVTdGVwc++8jOWboOS4uuaYr+mihOe6pueahO+8jOebtOaOpei/lOWbnlxyXG4gICAgY29uc3QgcmVzdWx0UHJvbWlzZSA9IHRoaXMuX3Jlc3VsdFdhaXRlci5wdXNoKG5ldyBQcm9taXNlT3V0KCkpLnByb21pc2U7XHJcbiAgICAvLy8g5b+F6KaB5pe277yM6K6p6YCJ5omL5Ye65YiXXHJcbiAgICBpZiAoXHJcbiAgICAgIC8vIOWmguaenOayoeacieS7u+S9leS4gOS4quWcqOi/kOihjOS4reeahOS7u+WKoe+8mumCo+S5iOeri+WIu+aJp+ihjFxyXG4gICAgICB0aGlzLl9ydW5uaW5ncy5zaXplID09PSAwIHx8XHJcbiAgICAgIC8vIOWmguaenOiHqueUsemYn+WIl+S4uuepuu+8jOS9huaYr+WAmeihpemYn+WIl+acieWtmOWcqOeahO+8mumCo+S5iOS5n+eri+WIu+aJp+ihjFxyXG4gICAgICAodGhpcy5fZnJlZUdlbi5zaXplID09PSAwICYmIHRoaXMuX2JlbmNoR2VuLnNpemUgIT09IDApXHJcbiAgICApIHtcclxuICAgICAgdGhpcy5fZGVxdWV1ZUdlbigpO1xyXG4gICAgfVxyXG4gICAgLy8gY29uc29sZS5sb2coKyt0aGlzLl90cmFjZUNvdW50KTtcclxuICAgIC8vIGlmICh0aGlzLl90cmFjZUNvdW50ID09PSAyKSB7XHJcbiAgICAvLyAgIGRlYnVnZ2VyO1xyXG4gICAgLy8gfVxyXG4gICAgcmV0dXJuIHJlc3VsdFByb21pc2U7XHJcbiAgfVxyXG4gIC8vIHByaXZhdGUgX3RyYWNlQ291bnQgPSAwO1xyXG4gIHByaXZhdGUgX2ZyZWVSZXN1bHQgPSBuZXcgRmFzdFF1ZW5lPFxyXG4gICAgTWl4QXN5bmNHZW5lcmF0b3IuUmVzdWx0V2l0aEZyb208VCwgZmFsc2U+XHJcbiAgPigpO1xyXG4gIHByaXZhdGUgX2JlbmNoUmVzdWx0ID0gbmV3IEZhc3RRdWVuZTxcclxuICAgIE1peEFzeW5jR2VuZXJhdG9yLlJlc3VsdFdpdGhGcm9tPFQsIHRydWU+XHJcbiAgPigpO1xyXG4gIHByaXZhdGUgX3Jlc3VsdFdhaXRlciA9IG5ldyBGYXN0UXVlbmU8XHJcbiAgICBQcm9taXNlT3V0PE1peEFzeW5jR2VuZXJhdG9yLlJlc3VsdDxUPj5cclxuICA+KCk7XHJcbiAgcmVhZG9ubHkgb25FcnJvciA9IG5ldyBFdnQ8TWl4QXN5bmNHZW5lcmF0b3IuRXJyb3I8VD4+KCk7XHJcbiAgbmV4dCgpIHtcclxuICAgIGlmICh0aGlzLmlzRG9uZSkge1xyXG4gICAgICByZXR1cm4gRE9ORSBhcyBQcm9taXNlPE1peEFzeW5jR2VuZXJhdG9yLlJlc3VsdDxUPj47XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcy5fZGVxdWV1ZVJlc3VsdCgpO1xyXG4gIH1cclxuICBnZXQgaXNEb25lKCkge1xyXG4gICAgcmV0dXJuIChcclxuICAgICAgLyogX2FsbEdlbkxpc3TkuLrnqbrkuZ/lsLHmhI/lkbPnnYBfcnVubmluZ+S4uuepuiAqLyB0aGlzLl9hbGxHZW5MaXN0LnNpemUgPT09IDAgJiZcclxuICAgICAgdGhpcy5fZnJlZVJlc3VsdC5zaXplID09PSAwICYmXHJcbiAgICAgIHRoaXMuX2JlbmNoUmVzdWx0LnNpemUgPT09IDBcclxuICAgICk7XHJcbiAgfVxyXG4gIGFzeW5jICp0b0FzeW5jSXRlcmF0b3IoKSB7XHJcbiAgICB3aGlsZSAodHJ1ZSkge1xyXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLm5leHQoKTtcclxuICAgICAgaWYgKHJlc3VsdC5zdGVwLmRvbmUpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgeWllbGQgcmVzdWx0LnN0ZXAudmFsdWU7XHJcbiAgICB9XHJcbiAgfVxyXG4gIGFzeW5jIHRvUHJvbWlzZSgpIHtcclxuICAgIHdoaWxlICh0cnVlKSB7XHJcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMubmV4dCgpO1xyXG4gICAgICBpZiAocmVzdWx0LnN0ZXAuZG9uZSkge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0=