UNPKG

@v4fire/core

Version:
128 lines (102 loc) 2.59 kB
/*! * V4Fire Core * https://github.com/V4Fire/Core * * Released under the MIT license * https://github.com/V4Fire/Core/blob/master/LICENSE */ /** * [[include:core/queue/merge/README.md]] * @packageDocumentation */ import SimpleQueue from 'core/queue/simple'; import AbstractQueue from 'core/queue/interface'; import type { HashFn, InnerQueue, CreateInnerQueue } from 'core/queue/merge/interface'; export * from 'core/queue/merge/interface'; /** * Implementation of a queue data structure with support of task merging by a specified hash function * @typeparam T - the queue element */ export default class MergeQueue<T> extends AbstractQueue<T> { /** * Type: the internal queue to store elements */ readonly InnerQueue!: InnerQueue<string>; /** @inheritDoc */ get head(): CanUndef<T> { if (this.length === 0) { return undefined; } return this.tasksMap.get(this.innerQueue.head!); } /** @inheritDoc */ get length(): number { return this.innerQueue.length; } /** * The internal queue to store elements */ protected innerQueue: this['InnerQueue']; /** * A map of registered tasks */ protected tasksMap: Map<string, T> = new Map(); /** * A function to calculate task hashes */ protected readonly hashFn: HashFn<T>; /** * @override * @param [hashFn] - a function to calculate task hashes */ constructor(hashFn?: HashFn<T>) { super(); this.innerQueue = this.createInnerQueue(); this.hashFn = hashFn ?? Object.fastHash.bind(Object); } /** @inheritDoc */ push(task: T): number { const hash = this.hashFn(task); if (!this.tasksMap.has(hash)) { this.tasksMap.set(hash, task); this.innerQueue.push(hash); } return this.length; } /** @inheritDoc */ pop(): CanUndef<T> { if (this.length === 0) { return; } const {head} = this; this.tasksMap.delete(this.innerQueue.head!); this.innerQueue.shift(); return head; } /** @inheritDoc */ clear(): void { if (this.length > 0) { this.innerQueue = this.createInnerQueue(); this.tasksMap = new Map(); } } /** @inheritDoc */ clone(): MergeQueue<T> { const newQueue = new MergeQueue<T>(this.hashFn); newQueue.tasksMap = new Map(this.tasksMap); if (this.innerQueue.clone != null) { newQueue.innerQueue = this.innerQueue.clone(); } else { for (const el of this.innerQueue) { newQueue.innerQueue.push(el); } } return newQueue; } /** * Returns a new blank internal queue to store elements */ protected createInnerQueue: CreateInnerQueue<this['InnerQueue']> = () => new SimpleQueue(); }