mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge pull request #4144 from Tyriar/priority_queue
Add PriorityTaskQueue
This commit is contained in:
@@ -16,7 +16,7 @@ import { tryDrawCustomChar } from 'browser/renderer/CustomGlyphs';
|
||||
import { excludeFromContrastRatioDemands, isPowerlineGlyph, isRestrictedPowerlineGlyph } from 'browser/renderer/RendererUtils';
|
||||
import { IUnicodeService } from 'common/services/Services';
|
||||
import { FourKeyMap } from 'common/MultiKeyMap';
|
||||
import { IdleTaskQueue } from 'common/Idle';
|
||||
import { IdleTaskQueue } from 'common/TaskQueue';
|
||||
|
||||
// For debugging purposes, it can be useful to set this to a really tiny value,
|
||||
// to verify that LRU eviction works.
|
||||
|
||||
@@ -12,7 +12,7 @@ import { addDisposableDomListener } from 'browser/Lifecycle';
|
||||
import { IColorSet, IRenderDebouncerWithCallback } from 'browser/Types';
|
||||
import { IOptionsService, IBufferService, IDecorationService } from 'common/services/Services';
|
||||
import { ICharSizeService, ICoreBrowserService, IRenderService } from 'browser/services/Services';
|
||||
import { DebouncedIdleTask } from 'common/Idle';
|
||||
import { DebouncedIdleTask } from 'common/TaskQueue';
|
||||
|
||||
interface ISelectionState {
|
||||
start: [number, number] | undefined;
|
||||
|
||||
@@ -3,27 +3,43 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* A queue of that runs tasks over several idle callbacks, trying to maintain the specified
|
||||
* frame rate. The tasks will run in the order they are enqueued, but they will run some time later,
|
||||
* and care should be taken to ensure they're non-urgent and will not introduce race conditions.
|
||||
*/
|
||||
export class IdleTaskQueue {
|
||||
import { isNode } from 'common/Platform';
|
||||
|
||||
interface ITaskQueue {
|
||||
/**
|
||||
* Adds a task to the queue which will run in a future idle callback.
|
||||
*/
|
||||
enqueue(task: () => void): void;
|
||||
|
||||
/**
|
||||
* Flushes the queue, running all remaining tasks synchronously.
|
||||
*/
|
||||
flush(): void;
|
||||
|
||||
/**
|
||||
* Clears any remaining tasks from the queue, these will not be run.
|
||||
*/
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
interface ITaskDeadline {
|
||||
timeRemaining(): number;
|
||||
}
|
||||
type CallbackWithDeadline = (deadline: ITaskDeadline) => void;
|
||||
|
||||
abstract class TaskQueue implements ITaskQueue {
|
||||
private _tasks: (() => void)[] = [];
|
||||
private _idleCallback?: number;
|
||||
private _i = 0;
|
||||
|
||||
/**
|
||||
* Adds a task to the queue which will run in a future idle callback.
|
||||
*/
|
||||
protected abstract _requestCallback(callback: CallbackWithDeadline): number;
|
||||
protected abstract _cancelCallback(identifier: number): void;
|
||||
|
||||
public enqueue(task: () => void): void {
|
||||
this._tasks.push(task);
|
||||
this._start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the queue, running all remaining tasks synchronously.
|
||||
*/
|
||||
public flush(): void {
|
||||
while (this._i < this._tasks.length) {
|
||||
this._tasks[this._i++]();
|
||||
@@ -31,9 +47,6 @@ export class IdleTaskQueue {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any remaining tasks from the queue, these will not be run.
|
||||
*/
|
||||
public clear(): void {
|
||||
if (this._idleCallback) {
|
||||
cancelIdleCallback(this._idleCallback);
|
||||
@@ -69,12 +82,55 @@ export class IdleTaskQueue {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A queue of that runs tasks over several tasks via setTimeout, trying to maintain above 60 frames
|
||||
* per second. The tasks will run in the order they are enqueued, but they will run some time later,
|
||||
* and care should be taken to ensure they're non-urgent and will not introduce race conditions.
|
||||
*/
|
||||
export class PriorityTaskQueue extends TaskQueue {
|
||||
protected _requestCallback(callback: CallbackWithDeadline): number {
|
||||
return setTimeout(() => callback(this._createDeadline(16)));
|
||||
}
|
||||
|
||||
protected _cancelCallback(identifier: number): void {
|
||||
clearTimeout(identifier);
|
||||
}
|
||||
|
||||
private _createDeadline(duration: number): ITaskDeadline {
|
||||
const end = performance.now() + duration;
|
||||
return {
|
||||
timeRemaining: () => Math.max(0, end - performance.now())
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class IdleTaskQueueInternal extends TaskQueue {
|
||||
protected _requestCallback(callback: IdleRequestCallback): number {
|
||||
return requestIdleCallback(callback);
|
||||
}
|
||||
|
||||
protected _cancelCallback(identifier: number): void {
|
||||
cancelIdleCallback(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A queue of that runs tasks over several idle callbacks, trying to respect the idle callback's
|
||||
* deadline given by the environment. The tasks will run in the order they are enqueued, but they
|
||||
* will run some time later, and care should be taken to ensure they're non-urgent and will not
|
||||
* introduce race conditions.
|
||||
*
|
||||
* This reverts to a {@link PriorityTaskQueue} if the environment does not support idle callbacks.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
export const IdleTaskQueue = (!isNode && 'requestIdleCallback' in window) ? IdleTaskQueueInternal : PriorityTaskQueue;
|
||||
|
||||
/**
|
||||
* An object that tracks a single debounced task that will run on the next idle frame. When called
|
||||
* multiple times, only the last set task will run.
|
||||
*/
|
||||
export class DebouncedIdleTask {
|
||||
private _queue: IdleTaskQueue;
|
||||
private _queue: ITaskQueue;
|
||||
|
||||
constructor() {
|
||||
this._queue = new IdleTaskQueue();
|
||||
Reference in New Issue
Block a user