UNPKG

reactronic

Version:

Reactronic - Transactional Reactive State Management

147 lines (146 loc) 6.29 kB
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()); }); }; import { Isolation } from "../Enums.js"; import { SxObject, Mvcc } from "./Mvcc.js"; import { Transaction } from "./Transaction.js"; export class Indicator extends SxObject { static create(hint, activationDelay, deactivationDelay, durationResolution) { return IndicatorImpl.createImpl(hint, activationDelay, deactivationDelay, durationResolution); } } export class IndicatorImpl extends Indicator { constructor() { super(...arguments); this.isBusy = false; this.counter = 0; this.workers = new Set(); this.busyDuration = 0; this.internals = { whenBusy: undefined, resolveWhenBusy: undefined, whenIdle: undefined, resolveWhenIdle: undefined, started: 0, activationDelay: -1, activationTimeout: undefined, deactivationDelay: -1, deactivationTimeout: undefined, durationResolution: 1, }; } whenBusy() { return __awaiter(this, void 0, void 0, function* () { if (this.internals.started === 0) { if (!this.internals.whenBusy) { this.internals.whenBusy = new Promise((resolve, reject) => { this.internals.resolveWhenBusy = resolve; }); } yield this.internals.whenBusy; } }); } whenIdle() { return __awaiter(this, void 0, void 0, function* () { if (this.internals.started !== 0) { if (!this.internals.whenIdle) { this.internals.whenIdle = new Promise((resolve, reject) => { this.internals.resolveWhenIdle = resolve; }); } yield this.internals.whenIdle; } }); } enter(worker) { this.counter++; const workers = this.workers = this.workers.toMutable(); workers.add(worker); IndicatorImpl.activate(this, this.internals.activationDelay); } leave(worker) { this.counter--; const workers = this.workers = this.workers.toMutable(); workers.delete(worker); IndicatorImpl.deactivate(this, this.internals.deactivationDelay); } static createImpl(hint, activationDelay, deactivationDelay, durationResolution) { return Transaction.run({ hint: "Indicator.create" }, IndicatorImpl.doCreate, hint, activationDelay, deactivationDelay, durationResolution); } static enter(mon, worker) { mon.enter(worker); } static leave(mon, worker) { mon.leave(worker); } static doCreate(hint, activationDelay, deactivationDelay, durationResolution) { const ind = new IndicatorImpl(); Mvcc.setHint(ind, hint); ind.internals.activationDelay = activationDelay; ind.internals.deactivationDelay = deactivationDelay; ind.internals.durationResolution = durationResolution; return ind; } static activate(mon, delay) { const active = mon.counter > 0; if (mon.internals.started === 0 && active) { mon.busyDuration = 0; mon.internals.started = performance.now(); if (mon.internals.whenBusy) { const resolve = mon.internals.resolveWhenBusy; mon.internals.whenBusy = undefined; mon.internals.resolveWhenBusy = undefined; resolve(); } IndicatorImpl.tick(mon); } if (delay >= 0) { if (mon.internals.activationTimeout === undefined) mon.internals.activationTimeout = setTimeout(() => Transaction.run({ hint: "Indicator.activate", isolation: Isolation.disjoinFromOuterAndInnerTransactions }, IndicatorImpl.activate, mon, -1), delay); } else if (active) mon.isBusy = true; } static deactivate(mon, delay) { if (delay >= 0) { clearTimeout(mon.internals.deactivationTimeout); mon.internals.deactivationTimeout = setTimeout(() => Transaction.run({ hint: "Indicator.deactivate", isolation: Isolation.disjoinFromOuterAndInnerTransactions }, IndicatorImpl.deactivate, mon, -1), delay); } else if (mon.counter <= 0) { mon.isBusy = false; mon.internals.activationTimeout = undefined; } if (mon.counter === 0 && mon.internals.started !== 0) { const resolution = mon.internals.durationResolution; mon.busyDuration = Math.round(resolution * (performance.now() - mon.internals.started)) / resolution; mon.internals.started = 0; if (mon.internals.whenIdle) { const resolve = mon.internals.resolveWhenIdle; mon.internals.whenIdle = undefined; mon.internals.resolveWhenIdle = undefined; resolve(); } } } static tick(mon) { if (mon.internals.started !== 0) { const resolution = mon.internals.durationResolution; mon.busyDuration = Math.round(resolution * (performance.now() - mon.internals.started)) / resolution; const t = globalThis !== null && globalThis !== void 0 ? globalThis : global; if (t.requestAnimationFrame) requestAnimationFrame(() => { Transaction.run(INDICATOR_TICK_OPTIONS, () => IndicatorImpl.tick(mon)); }); } } } const INDICATOR_TICK_OPTIONS = Object.freeze({ hint: "Indicator.tick", });