diff options
author | Austin Adams <git@austinjadams.com> | 2020-06-06 23:13:45 -0700 |
---|---|---|
committer | Austin Adams <git@austinjadams.com> | 2020-06-06 23:13:53 -0700 |
commit | 13a73a1a06588a8966627bd003ca8ea9dcfd5819 (patch) | |
tree | 923b7c7d7f0678380e61f68db927bafe222f87db | |
parent | f20db296461976de41d0ca97696a5f49a77990ba (diff) | |
download | novice-13a73a1a06588a8966627bd003ca8ea9dcfd5819.tar.gz novice-13a73a1a06588a8966627bd003ca8ea9dcfd5819.tar.xz |
Make workers async
This avoids the possibility of accidentally stepping while a step is still running
5 files changed, 44 insertions, 10 deletions
diff --git a/packages/novice-web/novice-web/workers/assembler/assembler-worker.ts b/packages/novice-web/novice-web/workers/assembler/assembler-worker.ts index fa3ef8e..97be2fc 100644 --- a/packages/novice-web/novice-web/workers/assembler/assembler-worker.ts +++ b/packages/novice-web/novice-web/workers/assembler/assembler-worker.ts @@ -9,10 +9,10 @@ class AssemblerWorker extends BaseWorker<AssemblerFrontendMessage, super(ctx); } - protected onFrontendMessage(msg: AssemblerFrontendMessage): void { + protected async onFrontendMessage(msg: AssemblerFrontendMessage): Promise<void> { switch (msg.kind) { case 'assemble': - this.assemble(msg.configName, msg.assemblyCode); + await this.assemble(msg.configName, msg.assemblyCode); break; // TODO: add never default again diff --git a/packages/novice-web/novice-web/workers/assembler/worker-entry.ts b/packages/novice-web/novice-web/workers/assembler/worker-entry.ts index 2f7fcad..5c91ec7 100644 --- a/packages/novice-web/novice-web/workers/assembler/worker-entry.ts +++ b/packages/novice-web/novice-web/workers/assembler/worker-entry.ts @@ -1,4 +1,4 @@ import { AssemblerWorker } from './assembler-worker'; const ctx: Worker = self as any; -new AssemblerWorker(ctx).register(); +new AssemblerWorker(ctx).run(); diff --git a/packages/novice-web/novice-web/workers/base-worker.ts b/packages/novice-web/novice-web/workers/base-worker.ts index 113c7c2..f1901d5 100644 --- a/packages/novice-web/novice-web/workers/base-worker.ts +++ b/packages/novice-web/novice-web/workers/base-worker.ts @@ -1,27 +1,61 @@ abstract class BaseWorker<FrontendMessageType, WorkerMessageType> { private ctx: Worker; + private messageQueue: FrontendMessageType[]; + private newFrontendMessage!: Promise<void>; + private triggerNewFrontendMessage!: () => void; public constructor(ctx: Worker) { this.ctx = ctx; + this.messageQueue = []; this.onMessageHandler = this.onMessageHandler.bind(this); + this.setupPromiseHack(); } - // Register events - public register(): void { + public run(): void { + // Register events this.ctx.onmessage = this.onMessageHandler; + + this.workerLoop(); } public onMessageHandler(event: MessageEvent): void { const msg: FrontendMessageType = event.data; + this.onFrontendMessage(msg); } - protected abstract onFrontendMessage(frontendMessage: FrontendMessageType): void; + protected abstract async onFrontendMessage(frontendMessage: FrontendMessageType): Promise<void>; protected sendWorkerMessage(workerMessage: WorkerMessageType): void { this.ctx.postMessage(workerMessage); } + + private setupPromiseHack(): void { + this.newFrontendMessage = new Promise<void>(resolve => { + this.triggerNewFrontendMessage = resolve; + }); + } + + private newMessageReady(msg: FrontendMessageType) { + this.messageQueue.push(msg); + // Even if the promise has already resolved, it's okay to call + // resolve() again as we are here: https://stackoverflow.com/a/43361520/321301 + this.triggerNewFrontendMessage(); + } + + private async workerLoop(): Promise<void> { + while (true) { + await this.newFrontendMessage; + this.setupPromiseHack(); + + let msg: FrontendMessageType|undefined; + + while (msg = this.messageQueue.shift()) { + await this.onFrontendMessage(msg); + } + } + } } export { BaseWorker }; diff --git a/packages/novice-web/novice-web/workers/debugger/debugger-worker.ts b/packages/novice-web/novice-web/workers/debugger/debugger-worker.ts index df12bdb..5322ccb 100644 --- a/packages/novice-web/novice-web/workers/debugger/debugger-worker.ts +++ b/packages/novice-web/novice-web/workers/debugger/debugger-worker.ts @@ -21,7 +21,7 @@ class DebuggerWorker extends BaseWorker<DebuggerFrontendMessage, }; } - protected onFrontendMessage(msg: DebuggerFrontendMessage): void { + protected async onFrontendMessage(msg: DebuggerFrontendMessage): Promise<void> { switch (msg.kind) { case 'reset': this.dbg = new SnitchDebugger(getIsa(msg.isa), this.io, -1, @@ -49,7 +49,7 @@ class DebuggerWorker extends BaseWorker<DebuggerFrontendMessage, throw new Error('must reset before stepping'); } - this.dbg.step(); + await this.dbg.step(); break; case 'unstep': @@ -79,7 +79,7 @@ class DebuggerWorker extends BaseWorker<DebuggerFrontendMessage, throw new Error('must reset before running'); } - this.dbg.run(); + await this.dbg.run(); break; default: diff --git a/packages/novice-web/novice-web/workers/debugger/worker-entry.ts b/packages/novice-web/novice-web/workers/debugger/worker-entry.ts index 0d75bd5..52186ff 100644 --- a/packages/novice-web/novice-web/workers/debugger/worker-entry.ts +++ b/packages/novice-web/novice-web/workers/debugger/worker-entry.ts @@ -1,4 +1,4 @@ import { DebuggerWorker } from './debugger-worker'; const ctx: Worker = self as any; -new DebuggerWorker(ctx).register(); +new DebuggerWorker(ctx).run(); |