constructor({ name, context, parallelism, parent, processor, getKey }) {
		this._name = name;
		this._context = context || "normal";
		this._parallelism = parallelism || 1;
		this._processor = processor;
		this._getKey =
			getKey ||
			/** @type {getKey<T, K>} */ (item => /** @type {T & K} */ (item));
		/** @type {Map<K, AsyncQueueEntry<T, K, R>>} */
		this._entries = new Map();
		/** @type {ArrayQueue<AsyncQueueEntry<T, K, R>>} */
		this._queued = new ArrayQueue();
		/** @type {AsyncQueue<T, K, R>[] | undefined} */
		this._children = undefined;
		this._activeTasks = 0;
		this._willEnsureProcessing = false;
		this._needProcessing = false;
		this._stopped = false;
		/** @type {AsyncQueue<T, K, R>} */
		this._root = parent ? parent._root : this;
		if (parent) {
			if (this._root._children === undefined) {
				this._root._children = [this];
			} else {
				this._root._children.push(this);
			}
		}

		this.hooks = {
			/** @type {AsyncSeriesHook<[T]>} */
			beforeAdd: new AsyncSeriesHook(["item"]),
			/** @type {SyncHook<[T]>} */
			added: new SyncHook(["item"]),
			/** @type {AsyncSeriesHook<[T]>} */
			beforeStart: new AsyncSeriesHook(["item"]),
			/** @type {SyncHook<[T]>} */
			started: new SyncHook(["item"]),
			/** @type {SyncHook<[T, WebpackError | null | undefined, R | null | undefined]>} */
			result: new SyncHook(["item", "error", "result"])
		};

		this._ensureProcessing = this._ensureProcessing.bind(this);
	}
@param {object} options options object
@param {string=} options.name name of the queue
@param {number=} options.parallelism how many items should be processed at once
@param {string=} options.context context of execution
@param {AsyncQueue<EXPECTED_ANY, EXPECTED_ANY, EXPECTED_ANY>=} options.parent parent queue, which will have priority over this queue and with shared parallelism
@param {getKey<T, K>=} options.getKey extract key from item
@param {Processor<T, R>} options.processor async function to process items