mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-24 06:52:40 -05:00
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:
parent
c986d0cf23
commit
b833ef8d24
1 changed files with 25 additions and 25 deletions
|
@ -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;
|
||||
if (stoppedThread) {
|
||||
let nextActiveThread = 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++;
|
||||
if (thread.stack.length !== 0 &&
|
||||
thread.status !== Thread.STATUS_DONE) {
|
||||
this.runtime.threads[nextActiveThread] = thread;
|
||||
nextActiveThread++;
|
||||
} else {
|
||||
doneThreads.push(thread);
|
||||
}
|
||||
}
|
||||
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++;
|
||||
this.runtime.threads.length = nextActiveThread;
|
||||
}
|
||||
}
|
||||
doneThreads.length = numDoneThreads;
|
||||
|
||||
return doneThreads;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue