<commit_before>/**
 * Copyright (c) 2022 The xterm.js authors. All rights reserved.
 * @license MIT
 */

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;

  protected abstract _requestCallback(callback: CallbackWithDeadline): number;
  protected abstract _cancelCallback(identifier: number): void;

  public enqueue(task: () => void): void {
    this._tasks.push(task);
    this._start();
  }

  public flush(): void {
    while (this._i < this._tasks.length) {
      this._tasks[this._i++]();
    }
    this.clear();
  }

  public clear(): void {
    if (this._idleCallback) {
      cancelIdleCallback(this._idleCallback);
      this._idleCallback = undefined;
    }
    this._i = 0;
    this._tasks.length = 0;
  }

  private _start(): void {
    if (!this._idleCallback) {
      this._idleCallback = requestIdleCallback(this._process.bind(this));
    }
  }

  private _process(deadline: IdleDeadline): void {
    this._idleCallback = undefined;
    let taskDuration = 0;
    let longestTask = 0;
    while (this._i < this._tasks.length) {
      taskDuration = performance.now();
      this._tasks[this._i++]();
      taskDuration = performance.now() - taskDuration;
      longestTask = Math.max(taskDuration, longestTask);
      // Guess the following task will take a similar time to the longest task in this batch, allow
      // additional room to try avoid exceeding the deadline
      if (longestTask * 1.5 > deadline.timeRemaining()) {
        this._start();
        return;
      }
    }
    this.clear();
  }
}

/**
 * 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: IdleTaskQueueInternal | PriorityTaskQueue;

  constructor() {
    this._queue = new IdleTaskQueue();
  }

  public set(task: () => void): void {
    this._queue.clear();
    this._queue.enqueue(task);
  }

  public flush(): void {
    this._queue.flush();
  }
}
<commit_msg>Use task queue interface<commit_after>/**
 * Copyright (c) 2022 The xterm.js authors. All rights reserved.
 * @license MIT
 */

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;

  protected abstract _requestCallback(callback: CallbackWithDeadline): number;
  protected abstract _cancelCallback(identifier: number): void;

  public enqueue(task: () => void): void {
    this._tasks.push(task);
    this._start();
  }

  public flush(): void {
    while (this._i < this._tasks.length) {
      this._tasks[this._i++]();
    }
    this.clear();
  }

  public clear(): void {
    if (this._idleCallback) {
      cancelIdleCallback(this._idleCallback);
      this._idleCallback = undefined;
    }
    this._i = 0;
    this._tasks.length = 0;
  }

  private _start(): void {
    if (!this._idleCallback) {
      this._idleCallback = requestIdleCallback(this._process.bind(this));
    }
  }

  private _process(deadline: IdleDeadline): void {
    this._idleCallback = undefined;
    let taskDuration = 0;
    let longestTask = 0;
    while (this._i < this._tasks.length) {
      taskDuration = performance.now();
      this._tasks[this._i++]();
      taskDuration = performance.now() - taskDuration;
      longestTask = Math.max(taskDuration, longestTask);
      // Guess the following task will take a similar time to the longest task in this batch, allow
      // additional room to try avoid exceeding the deadline
      if (longestTask * 1.5 > deadline.timeRemaining()) {
        this._start();
        return;
      }
    }
    this.clear();
  }
}

/**
 * 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: ITaskQueue;

  constructor() {
    this._queue = new IdleTaskQueue();
  }

  public set(task: () => void): void {
    this._queue.clear();
    this._queue.enqueue(task);
  }

  public flush(): void {
    this._queue.flush();
  }
}

{'fraction_non_alphanumeric': 0.10692488262910799, 'fraction_numerical': 0.003755868544600939, 'mean_word_length': 3.456589958158996, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5736097', 'n_tokens_mistral': 2467, 'n_tokens_neox': 2423, 'n_words': 808}