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.
This commit is contained in:
Michael "Z" Goddard 2018-10-19 16:43:36 -04:00
parent c986d0cf23
commit b833ef8d24
No known key found for this signature in database
GPG key ID: 762CD40DD5349872

View file

@ -74,7 +74,7 @@ class Sequencer {
let numActiveThreads = Infinity; let numActiveThreads = Infinity;
// Whether `stepThreads` has run through a full single tick. // Whether `stepThreads` has run through a full single tick.
let ranFirstTick = false; let ranFirstTick = false;
const doneThreads = this.runtime.threads.map(() => null); const doneThreads = [];
// Conditions for continuing to stepping threads: // Conditions for continuing to stepping threads:
// 1. We must have threads in the list, and some must be active. // 1. We must have threads in the list, and some must be active.
// 2. Time elapsed must be less than WORK_TIME. // 2. Time elapsed must be less than WORK_TIME.
@ -91,19 +91,17 @@ class Sequencer {
} }
numActiveThreads = 0; numActiveThreads = 0;
let stoppedThread = false;
// Attempt to run each thread one time. // Attempt to run each thread one time.
for (let i = 0; i < this.runtime.threads.length; i++) { for (let i = 0; i < this.runtime.threads.length; i++) {
const activeThread = this.runtime.threads[i]; const activeThread = this.runtime.threads[i];
// Check if the thread is done so it is not executed.
if (activeThread.stack.length === 0 || if (activeThread.stack.length === 0 ||
activeThread.status === Thread.STATUS_DONE) { activeThread.status === Thread.STATUS_DONE) {
// Finished with this thread. // Finished with this thread.
doneThreads[i] = activeThread; stoppedThread = true;
continue; 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 && if (activeThread.status === Thread.STATUS_YIELD_TICK &&
!ranFirstTick) { !ranFirstTick) {
// Clear single-tick yield from the last call of `stepThreads`. // Clear single-tick yield from the last call of `stepThreads`.
@ -130,6 +128,13 @@ class Sequencer {
if (activeThread.status === Thread.STATUS_RUNNING) { if (activeThread.status === Thread.STATUS_RUNNING) {
numActiveThreads++; 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 // We successfully ticked once. Prevents running STATUS_YIELD_TICK
// threads on the next tick. // threads on the next tick.
@ -138,28 +143,23 @@ class Sequencer {
if (this.runtime.profiler !== null) { if (this.runtime.profiler !== null) {
this.runtime.profiler.stop(); this.runtime.profiler.stop();
} }
}
// Filter inactive threads from `this.runtime.threads`. // Filter inactive threads from `this.runtime.threads`.
numActiveThreads = 0; if (stoppedThread) {
let nextActiveThread = 0;
for (let i = 0; i < this.runtime.threads.length; i++) { for (let i = 0; i < this.runtime.threads.length; i++) {
const thread = this.runtime.threads[i]; const thread = this.runtime.threads[i];
if (doneThreads[i] === null) { if (thread.stack.length !== 0 &&
this.runtime.threads[numActiveThreads] = thread; thread.status !== Thread.STATUS_DONE) {
numActiveThreads++; this.runtime.threads[nextActiveThread] = thread;
nextActiveThread++;
} else {
doneThreads.push(thread);
} }
} }
this.runtime.threads.length = numActiveThreads; this.runtime.threads.length = nextActiveThread;
// 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++;
} }
} }
doneThreads.length = numDoneThreads;
return doneThreads; return doneThreads;
} }