aboutsummaryrefslogtreecommitdiffgithub
diff options
context:
space:
mode:
authorAustin Adams <git@austinjadams.com>2020-06-06 23:13:45 -0700
committerAustin Adams <git@austinjadams.com>2020-06-06 23:13:53 -0700
commit13a73a1a06588a8966627bd003ca8ea9dcfd5819 (patch)
tree923b7c7d7f0678380e61f68db927bafe222f87db
parentf20db296461976de41d0ca97696a5f49a77990ba (diff)
downloadnovice-13a73a1a06588a8966627bd003ca8ea9dcfd5819.tar.gz
novice-13a73a1a06588a8966627bd003ca8ea9dcfd5819.tar.xz
Make workers async
This avoids the possibility of accidentally stepping while a step is still running
-rw-r--r--packages/novice-web/novice-web/workers/assembler/assembler-worker.ts4
-rw-r--r--packages/novice-web/novice-web/workers/assembler/worker-entry.ts2
-rw-r--r--packages/novice-web/novice-web/workers/base-worker.ts40
-rw-r--r--packages/novice-web/novice-web/workers/debugger/debugger-worker.ts6
-rw-r--r--packages/novice-web/novice-web/workers/debugger/worker-entry.ts2
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();