@v4fire/client
Version:
V4Fire client core library
149 lines (116 loc) • 2.44 kB
text/typescript
/*!
* V4Fire Client Core
* https://github.com/V4Fire/Client
*
* Released under the MIT license
* https://github.com/V4Fire/Client/blob/master/LICENSE
*/
/**
* [[include:core/render/README.md]]
* @packageDocumentation
*/
import {
daemon,
queue,
add as addToQueue,
TASKS_PER_TICK,
DELAY
} from 'core/render/const';
export * from 'core/render/const';
export * from 'core/render/interface';
let
inProgress = false,
isStarted = false;
queue.add = function add<T = unknown>(...args: unknown[]): T {
const
res = addToQueue(...args);
if (!isStarted) {
run();
}
return res;
};
/**
* Restarts the render daemon
*/
export function restart(): void {
isStarted = false;
inProgress = false;
run();
}
/**
* Restarts the render daemon
* (it runs on the next tick)
*/
export function deferRestart(): void {
isStarted = false;
inProgress = false;
daemon.clearAll();
runOnNextTick();
}
function run(): void {
daemon.clearAll();
const exec = async () => {
inProgress = true;
isStarted = true;
let
time = Date.now(),
done = TASKS_PER_TICK;
for (let w = queue.values(), el = w.next(); !el.done; el = w.next()) {
const
val = el.value;
if (done <= 0 || Date.now() - time > DELAY) {
await daemon.idle({timeout: DELAY});
time = Date.now();
// eslint-disable-next-line require-atomic-updates
done = TASKS_PER_TICK;
}
const
w = val.weight ?? 1;
if (done - w < 0 && done !== TASKS_PER_TICK) {
continue;
}
const
canRender = val.fn();
const exec = (canRender) => {
if (Object.isTruly(canRender)) {
done -= val.weight ?? 1;
queue.delete(val);
}
};
if (Object.isPromise(canRender)) {
const now = Date.now();
await canRender.then(exec);
if (now - time > DELAY) {
time = now;
done += val.weight ?? 1;
}
} else {
exec(canRender);
}
}
if (!runOnNextTick()) {
daemon.setImmediate(() => {
inProgress = canProcessing();
isStarted = inProgress;
if (inProgress) {
runOnNextTick();
}
});
}
};
if (inProgress || queue.size >= TASKS_PER_TICK) {
exec().catch(stderr);
} else {
daemon.setImmediate(() => exec().catch(stderr));
}
}
function canProcessing(): boolean {
return Boolean(queue.size);
}
function runOnNextTick(): boolean {
if (canProcessing()) {
daemon.requestIdleCallback(run, {timeout: DELAY});
return true;
}
return false;
}