From 732e7dc93125d00f9fdd39e06ac303a458a36373 Mon Sep 17 00:00:00 2001 From: tamaina Date: Wed, 17 May 2023 17:13:32 +0000 Subject: [PATCH] wip --- .../src/components/MkImgWithBlurhash.vue | 41 ++++++++---- .../src/scripts/worker-multi-dispatch.ts | 62 +++++++++++++++++++ 2 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 packages/frontend/src/scripts/worker-multi-dispatch.ts diff --git a/packages/frontend/src/components/MkImgWithBlurhash.vue b/packages/frontend/src/components/MkImgWithBlurhash.vue index ca912fabf5..2967fad450 100644 --- a/packages/frontend/src/components/MkImgWithBlurhash.vue +++ b/packages/frontend/src/components/MkImgWithBlurhash.vue @@ -18,12 +18,21 @@ diff --git a/packages/frontend/src/scripts/worker-multi-dispatch.ts b/packages/frontend/src/scripts/worker-multi-dispatch.ts new file mode 100644 index 0000000000..f1f9ae53b4 --- /dev/null +++ b/packages/frontend/src/scripts/worker-multi-dispatch.ts @@ -0,0 +1,62 @@ +function defaultUseWorkerNumber(prev: number, totalWorkers: number) { + return prev + 1; +} + +export class WorkerMultiDispatch { + private sym = Symbol('WorkerMultiDispatch'); + public workers: Worker[] = []; + private prevWorkerNumber = 0; + private getUseWorkerNumber = defaultUseWorkerNumber; + private finalizationRegistry: FinalizationRegistry; + + constructor(workerConstructor: () => Worker, concurrency: number, getUseWorkerNumber = defaultUseWorkerNumber) { + this.getUseWorkerNumber = getUseWorkerNumber; + for (let i = 0; i < concurrency; i++) { + this.workers.push(workerConstructor()); + } + + this.finalizationRegistry = new FinalizationRegistry(() => { + this.terminate(); + }); + this.finalizationRegistry.register(this, this.sym); + + if (_DEV_) console.log('WorkerMultiDispatch: Created', this); + } + + public postMessage(message: POST, options?: Transferable[] | StructuredSerializeOptions, useWorkerNumber: typeof defaultUseWorkerNumber = this.getUseWorkerNumber) { + let workerNumber = useWorkerNumber(this.prevWorkerNumber, this.workers.length); + workerNumber = Math.abs(Math.round(workerNumber)) % this.workers.length; + if (_DEV_) console.log('WorkerMultiDispatch: Posting message to worker', workerNumber, useWorkerNumber); + this.prevWorkerNumber = workerNumber; + + // 不毛だがunionをoverloadに突っ込めない + // https://stackoverflow.com/questions/66507585/overload-signatures-union-types-and-no-overload-matches-this-call-error + // https://github.com/microsoft/TypeScript/issues/14107 + if (Array.isArray(options)) { + this.workers[workerNumber].postMessage(message, options); + } else { + this.workers[workerNumber].postMessage(message, options); + } + return workerNumber; + } + + public addListener(callback: (this: Worker, ev: MessageEvent) => any, options?: boolean | AddEventListenerOptions) { + this.workers.forEach(worker => { + worker.addEventListener('message', callback, options); + }); + } + + public removeListener(callback: (this: Worker, ev: MessageEvent) => any, options?: boolean | AddEventListenerOptions) { + this.workers.forEach(worker => { + worker.removeEventListener('message', callback, options); + }); + } + + public terminate() { + this.workers.forEach(worker => { + worker.terminate(); + }); + this.workers = []; + this.finalizationRegistry.unregister(this); + } +}