@soapbox.pub/wasmboy
Version:
Soapbox fork of Wasmboy.
99 lines (83 loc) • 3.12 kB
JavaScript
// WasmBoy Modules
import { WasmBoyGraphics } from '../graphics/graphics';
import { WasmBoyAudio } from '../audio/audio';
import { WasmBoyController } from '../controller/controller';
import { WasmBoyMemory } from '../memory/memory';
// Import our Smart Worker Interface
import { SmartWorker } from './smartworker';
import { WORKER_MESSAGE_TYPE, WORKER_ID } from './constants';
export const instantiateWorkers = async () => {
const libWorker = new SmartWorker(
new Worker(new URL('worker/wasmboy.wasm.worker.js', import.meta.url), { type: 'module' }),
WORKER_ID.LIB
);
const graphicsWorker = new SmartWorker(
new Worker(new URL('worker/graphics.worker.js', import.meta.url), { type: 'module' }),
WORKER_ID.GRAPHICS
);
const audioWorker = new SmartWorker(new Worker(new URL('worker/audio.worker.js', import.meta.url), { type: 'module' }), WORKER_ID.AUDIO);
const controllerWorker = new SmartWorker(
new Worker(new URL('worker/controller.worker.js', import.meta.url), { type: 'module' }),
WORKER_ID.CONTROLLER
);
const memoryWorker = new SmartWorker(
new Worker(new URL('worker/memory.worker.js', import.meta.url), { type: 'module' }),
WORKER_ID.MEMORY
);
// Create an array of promises for when each worker is ready
const workerReadyPromises = [];
// Add our workers to an array,
const childWorkers = [graphicsWorker, audioWorker, controllerWorker, memoryWorker];
// Create a messaging channel between our main lib worker,
// And all of the children workers
childWorkers.forEach(childWorker => {
// Create our message channel
// https://stackoverflow.com/questions/14191394/web-workers-communication-using-messagechannel-html5
const messageChannel = new MessageChannel();
const workerReadyPromise = new Promise(resolve => {
// Our resolve function
let messagesReceived = 0;
const tryResolveWorkerReady = () => {
messagesReceived++;
if (messagesReceived >= 2) {
resolve();
}
};
// Post our connect messages
libWorker
.postMessage(
{
type: WORKER_MESSAGE_TYPE.CONNECT,
workerId: childWorker.id,
ports: [messageChannel.port1]
},
[messageChannel.port1]
)
.then(() => {
tryResolveWorkerReady();
});
childWorker
.postMessage(
{
type: WORKER_MESSAGE_TYPE.CONNECT,
workerId: libWorker.id,
ports: [messageChannel.port2]
},
[messageChannel.port2]
)
.then(() => {
tryResolveWorkerReady();
});
});
workerReadyPromises.push(workerReadyPromise);
});
// Wait for all workers to be ready
await Promise.all(workerReadyPromises);
// Finally, pass the ready workers to all of our children lib
WasmBoyGraphics.setWorker(graphicsWorker);
WasmBoyAudio.setWorker(audioWorker);
WasmBoyController.setWorker(controllerWorker);
WasmBoyMemory.setWorker(memoryWorker);
// Return the main worker for the main lib
return libWorker;
};