From c986d0cf23630d7ec37c06e053cc81e79aee5461 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Fri, 19 Oct 2018 16:37:33 -0400 Subject: [PATCH 1/3] test that broadcast_and_wait can yield and continue in the same tick --- ...roadcast-and-wait-can-continue-same-tick.sb2 | Bin 0 -> 55188 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/fixtures/execute/event-broadcast-and-wait-can-continue-same-tick.sb2 diff --git a/test/fixtures/execute/event-broadcast-and-wait-can-continue-same-tick.sb2 b/test/fixtures/execute/event-broadcast-and-wait-can-continue-same-tick.sb2 new file mode 100644 index 0000000000000000000000000000000000000000..3e3e3c85e757712acfb71849a0a76c8520d3011a GIT binary patch literal 55188 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 literal 0 HcmV?d00001 From b833ef8d249f43986f0738277bbde505aeee0d1c Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Fri, 19 Oct 2018 16:43:36 -0400 Subject: [PATCH 2/3] remove finished threads every loop of all threads When all threads are looped, finished threads must be removed so threads that are waiting for those to complete and be removed may continue executing. This effects broadcast and wait for example. The threads created by broadcast and wait can finish in the same tick and must be removed from the list of threads so that broadcast and wait knows to stop waiting. --- src/engine/sequencer.js | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 7d40dd85a..5b3fcf005 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -74,7 +74,7 @@ class Sequencer { let numActiveThreads = Infinity; // Whether `stepThreads` has run through a full single tick. let ranFirstTick = false; - const doneThreads = this.runtime.threads.map(() => null); + const doneThreads = []; // Conditions for continuing to stepping threads: // 1. We must have threads in the list, and some must be active. // 2. Time elapsed must be less than WORK_TIME. @@ -91,19 +91,17 @@ class Sequencer { } numActiveThreads = 0; + let stoppedThread = false; // Attempt to run each thread one time. for (let i = 0; i < this.runtime.threads.length; i++) { const activeThread = this.runtime.threads[i]; + // Check if the thread is done so it is not executed. if (activeThread.stack.length === 0 || activeThread.status === Thread.STATUS_DONE) { // Finished with this thread. - doneThreads[i] = activeThread; + stoppedThread = true; continue; } - // A thread was removed, added or this thread was restarted. - if (doneThreads[i] !== null) { - doneThreads[i] = null; - } if (activeThread.status === Thread.STATUS_YIELD_TICK && !ranFirstTick) { // Clear single-tick yield from the last call of `stepThreads`. @@ -130,6 +128,13 @@ class Sequencer { if (activeThread.status === Thread.STATUS_RUNNING) { numActiveThreads++; } + // Check if the thread completed while it just stepped to make + // sure we remove it before the next iteration of all threads. + if (activeThread.stack.length === 0 || + activeThread.status === Thread.STATUS_DONE) { + // Finished with this thread. + stoppedThread = true; + } } // We successfully ticked once. Prevents running STATUS_YIELD_TICK // threads on the next tick. @@ -138,28 +143,23 @@ class Sequencer { if (this.runtime.profiler !== null) { this.runtime.profiler.stop(); } - } - // Filter inactive threads from `this.runtime.threads`. - numActiveThreads = 0; - for (let i = 0; i < this.runtime.threads.length; i++) { - const thread = this.runtime.threads[i]; - if (doneThreads[i] === null) { - this.runtime.threads[numActiveThreads] = thread; - numActiveThreads++; - } - } - this.runtime.threads.length = numActiveThreads; - // Filter undefined and null values from `doneThreads`. - let numDoneThreads = 0; - for (let i = 0; i < doneThreads.length; i++) { - const maybeThread = doneThreads[i]; - if (maybeThread !== null) { - doneThreads[numDoneThreads] = maybeThread; - numDoneThreads++; + // Filter inactive threads from `this.runtime.threads`. + if (stoppedThread) { + let nextActiveThread = 0; + for (let i = 0; i < this.runtime.threads.length; i++) { + const thread = this.runtime.threads[i]; + if (thread.stack.length !== 0 && + thread.status !== Thread.STATUS_DONE) { + this.runtime.threads[nextActiveThread] = thread; + nextActiveThread++; + } else { + doneThreads.push(thread); + } + } + this.runtime.threads.length = nextActiveThread; } } - doneThreads.length = numDoneThreads; return doneThreads; } From 2ffa8eb3334fd3b71cf63ca7b8ebc27ee898bc18 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Wed, 31 Oct 2018 17:56:12 -0400 Subject: [PATCH 3/3] update runtime thread tests Threads are now removed after every "inner" step. Any thread that reaches its DONE conditions is immediately removed instead of requiring an extra step to remove it. As such tests that check the number of threads have been updated to consider this. --- src/engine/runtime.js | 10 +++ .../hat-threads-run-every-frame.js | 68 ++++++++++++------- .../monitor-threads-run-every-frame.js | 20 ++++-- test/integration/monitors.js | 6 +- test/unit/engine_sequencer.js | 3 +- 5 files changed, 73 insertions(+), 34 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 2e17500cd..a7b10d9ba 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -188,6 +188,13 @@ class Runtime extends EventEmitter { */ this._nonMonitorThreadCount = 0; + /** + * All threads that finished running and were removed from this.threads + * by behaviour in Sequencer.stepThreads. + * @type {Array} + */ + this._lastStepDoneThreads = null; + /** * Currently known number of clones, used to enforce clone limit. * @type {number} @@ -1560,6 +1567,9 @@ class Runtime extends EventEmitter { this._emitProjectRunStatus( this.threads.length + doneThreads.length - this._getMonitorThreadCount([...this.threads, ...doneThreads])); + // Store threads that completed this iteration for testing and other + // internal purposes. + this._lastStepDoneThreads = doneThreads; if (this.renderer) { // @todo: Only render when this.redrawRequested or clones rendered. if (this.profiler !== null) { diff --git a/test/integration/hat-threads-run-every-frame.js b/test/integration/hat-threads-run-every-frame.js index 8a80ef761..5d3c3527f 100644 --- a/test/integration/hat-threads-run-every-frame.js +++ b/test/integration/hat-threads-run-every-frame.js @@ -45,15 +45,19 @@ test('edge activated hat thread runs once every frame', t => { t.equal(vm.runtime.threads.length, 0); vm.runtime._step(); - t.equal(vm.runtime.threads.length, 1); - checkIsHatThread(t, vm, vm.runtime.threads[0]); - t.assert(vm.runtime.threads[0].status === Thread.STATUS_DONE); + let threads = vm.runtime._lastStepDoneThreads; + t.equal(vm.runtime.threads.length, 0); + t.equal(threads.length, 1); + checkIsHatThread(t, vm, threads[0]); + t.assert(threads[0].status === Thread.STATUS_DONE); // Check that the hat thread is added again when another step is taken vm.runtime._step(); - t.equal(vm.runtime.threads.length, 1); - checkIsHatThread(t, vm, vm.runtime.threads[0]); - t.assert(vm.runtime.threads[0].status === Thread.STATUS_DONE); + threads = vm.runtime._lastStepDoneThreads; + t.equal(vm.runtime.threads.length, 0); + t.equal(threads.length, 1); + checkIsHatThread(t, vm, threads[0]); + t.assert(threads[0].status === Thread.STATUS_DONE); t.end(); }); }); @@ -79,15 +83,19 @@ test('edge activated hat thread not added twice', t => { t.equal(vm.runtime.threads.length, 0); vm.runtime._step(); + let doneThreads = vm.runtime._lastStepDoneThreads; t.equal(vm.runtime.threads.length, 1); + t.equal(doneThreads.length, 0); const prevThread = vm.runtime.threads[0]; checkIsHatThread(t, vm, vm.runtime.threads[0]); t.assert(vm.runtime.threads[0].status === Thread.STATUS_RUNNING); // Check that no new threads are added when another step is taken vm.runtime._step(); + doneThreads = vm.runtime._lastStepDoneThreads; // There should now be one done hat thread and one new hat thread to run t.equal(vm.runtime.threads.length, 1); + t.equal(doneThreads.length, 0); checkIsHatThread(t, vm, vm.runtime.threads[0]); t.assert(vm.runtime.threads[0] === prevThread); t.end(); @@ -115,29 +123,33 @@ test('edge activated hat thread does not interrupt stack click thread', t => { t.equal(vm.runtime.threads.length, 0); vm.runtime._step(); - t.equal(vm.runtime.threads.length, 1); - checkIsHatThread(t, vm, vm.runtime.threads[0]); - t.assert(vm.runtime.threads[0].status === Thread.STATUS_DONE); + let doneThreads = vm.runtime._lastStepDoneThreads; + t.equal(vm.runtime.threads.length, 0); + t.equal(doneThreads.length, 1); + checkIsHatThread(t, vm, doneThreads[0]); + t.assert(doneThreads[0].status === Thread.STATUS_DONE); // Add stack click thread on this hat - vm.runtime.toggleScript(vm.runtime.threads[0].topBlock, {stackClick: true}); + vm.runtime.toggleScript(doneThreads[0].topBlock, {stackClick: true}); // Check that the hat thread is added again when another step is taken vm.runtime._step(); - t.equal(vm.runtime.threads.length, 2); + doneThreads = vm.runtime._lastStepDoneThreads; + t.equal(vm.runtime.threads.length, 0); + t.equal(doneThreads.length, 2); let hatThread; let stackClickThread; - if (vm.runtime.threads[0].stackClick) { - stackClickThread = vm.runtime.threads[0]; - hatThread = vm.runtime.threads[1]; + if (doneThreads[0].stackClick) { + stackClickThread = doneThreads[0]; + hatThread = doneThreads[1]; } else { - stackClickThread = vm.runtime.threads[1]; - hatThread = vm.runtime.threads[0]; + stackClickThread = doneThreads[1]; + hatThread = doneThreads[0]; } checkIsHatThread(t, vm, hatThread); checkIsStackClickThread(t, vm, stackClickThread); - t.assert(vm.runtime.threads[0].status === Thread.STATUS_DONE); - t.assert(vm.runtime.threads[1].status === Thread.STATUS_DONE); + t.assert(doneThreads[0].status === Thread.STATUS_DONE); + t.assert(doneThreads[1].status === Thread.STATUS_DONE); t.end(); }); }); @@ -163,7 +175,9 @@ test('edge activated hat thread does not interrupt stack click thread', t => { t.equal(vm.runtime.threads.length, 0); vm.runtime._step(); + let doneThreads = vm.runtime._lastStepDoneThreads; t.equal(vm.runtime.threads.length, 1); + t.equal(doneThreads.length, 0); checkIsHatThread(t, vm, vm.runtime.threads[0]); t.assert(vm.runtime.threads[0].status === Thread.STATUS_RUNNING); @@ -174,20 +188,22 @@ test('edge activated hat thread does not interrupt stack click thread', t => { // Check that the hat thread is added again when another step is taken vm.runtime._step(); - t.equal(vm.runtime.threads.length, 2); + doneThreads = vm.runtime._lastStepDoneThreads; + t.equal(vm.runtime.threads.length, 0); + t.equal(doneThreads.length, 2); let hatThread; let stackClickThread; - if (vm.runtime.threads[0].stackClick) { - stackClickThread = vm.runtime.threads[0]; - hatThread = vm.runtime.threads[1]; + if (doneThreads[0].stackClick) { + stackClickThread = doneThreads[0]; + hatThread = doneThreads[1]; } else { - stackClickThread = vm.runtime.threads[1]; - hatThread = vm.runtime.threads[0]; + stackClickThread = doneThreads[1]; + hatThread = doneThreads[0]; } checkIsHatThread(t, vm, hatThread); checkIsStackClickThread(t, vm, stackClickThread); - t.assert(vm.runtime.threads[0].status === Thread.STATUS_DONE); - t.assert(vm.runtime.threads[1].status === Thread.STATUS_DONE); + t.assert(doneThreads[0].status === Thread.STATUS_DONE); + t.assert(doneThreads[1].status === Thread.STATUS_DONE); t.end(); }); }); diff --git a/test/integration/monitor-threads-run-every-frame.js b/test/integration/monitor-threads-run-every-frame.js index cebd73142..bcfe5daa7 100644 --- a/test/integration/monitor-threads-run-every-frame.js +++ b/test/integration/monitor-threads-run-every-frame.js @@ -55,13 +55,19 @@ test('monitor thread runs every frame', t => { t.equal(vm.runtime.threads.length, 0); vm.runtime._step(); - checkMonitorThreadPresent(t, vm.runtime.threads); - t.assert(vm.runtime.threads[0].status === Thread.STATUS_DONE); + let doneThreads = vm.runtime._lastStepDoneThreads; + t.equal(vm.runtime.threads.length, 0); + t.equal(doneThreads.length, 1); + checkMonitorThreadPresent(t, doneThreads); + t.assert(doneThreads[0].status === Thread.STATUS_DONE); // Check that both are added again when another step is taken vm.runtime._step(); - checkMonitorThreadPresent(t, vm.runtime.threads); - t.assert(vm.runtime.threads[0].status === Thread.STATUS_DONE); + doneThreads = vm.runtime._lastStepDoneThreads; + t.equal(vm.runtime.threads.length, 0); + t.equal(doneThreads.length, 1); + checkMonitorThreadPresent(t, doneThreads); + t.assert(doneThreads[0].status === Thread.STATUS_DONE); t.end(); }); }); @@ -103,12 +109,18 @@ test('monitor thread not added twice', t => { t.equal(vm.runtime.threads.length, 0); vm.runtime._step(); + let doneThreads = vm.runtime._lastStepDoneThreads; + t.equal(vm.runtime.threads.length, 1); + t.equal(doneThreads.length, 0); checkMonitorThreadPresent(t, vm.runtime.threads); t.assert(vm.runtime.threads[0].status === Thread.STATUS_RUNNING); const prevThread = vm.runtime.threads[0]; // Check that both are added again when another step is taken vm.runtime._step(); + doneThreads = vm.runtime._lastStepDoneThreads; + t.equal(vm.runtime.threads.length, 1); + t.equal(doneThreads.length, 0); checkMonitorThreadPresent(t, vm.runtime.threads); t.equal(vm.runtime.threads[0], prevThread); t.end(); diff --git a/test/integration/monitors.js b/test/integration/monitors.js index 52bc5b0f0..38e89b43e 100644 --- a/test/integration/monitors.js +++ b/test/integration/monitors.js @@ -14,8 +14,10 @@ test('importing sb2 project with monitors', t => { // Evaluate playground data and exit vm.on('playgroundData', e => { const threads = JSON.parse(e.threads); - // All monitors should leave threads running - t.equal(threads.length, 5); + // All monitors should create threads that finish during the step and + // are revoved from runtime.threads. + t.equal(threads.length, 0); + t.equal(vm.runtime._lastStepDoneThreads.length, 5); // There should be one additional hidden monitor that is in the monitorState but // does not start a thread. t.equal(vm.runtime._monitorState.size, 6); diff --git a/test/unit/engine_sequencer.js b/test/unit/engine_sequencer.js index 55faeb69e..622dc64b3 100644 --- a/test/unit/engine_sequencer.js +++ b/test/unit/engine_sequencer.js @@ -181,8 +181,7 @@ test('stepThreads', t => { t.strictEquals(s.stepThreads().length, 0); generateThread(r); t.strictEquals(r.threads.length, 1); - t.strictEquals(s.stepThreads().length, 0); - r.threads[0].status = Thread.STATUS_RUNNING; + // Threads should be marked DONE and removed in the same step they finish. t.strictEquals(s.stepThreads().length, 1); t.end();