Merge pull request #793 from cwillisf/remove-threads-safely

Make _removeThread safe during thread iteration
This commit is contained in:
Chris Willis-Ford 2017-12-06 17:18:10 -08:00 committed by GitHub
commit e7bbad60e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -806,17 +806,14 @@ class Runtime extends EventEmitter {
} }
/** /**
* Remove a thread from the list of threads. * Stop a thread: stop running it immediately, and remove it from the thread list later.
* @param {?Thread} thread Thread object to remove from actives * @param {!Thread} thread Thread object to remove from actives
*/ */
_removeThread (thread) { _stopThread (thread) {
// Mark the thread for later removal
thread.isKilled = true;
// Inform sequencer to stop executing that thread. // Inform sequencer to stop executing that thread.
this.sequencer.retireThread(thread); this.sequencer.retireThread(thread);
// Remove from the list.
const i = this.threads.indexOf(thread);
if (i > -1) {
this.threads.splice(i, 1);
}
} }
/** /**
@ -879,7 +876,7 @@ class Runtime extends EventEmitter {
// edge activated hat thread that runs every frame // edge activated hat thread that runs every frame
continue; continue;
} }
this._removeThread(this.threads[i]); this._stopThread(this.threads[i]);
return; return;
} }
} }
@ -1055,8 +1052,7 @@ class Runtime extends EventEmitter {
continue; continue;
} }
if (this.threads[i].target === target) { if (this.threads[i].target === target) {
this.threads[i].isKilled = true; this._stopThread(this.threads[i]);
this._removeThread(this.threads[i]);
} }
} }
} }
@ -1096,11 +1092,7 @@ class Runtime extends EventEmitter {
} }
this.targets = newTargets; this.targets = newTargets;
// Dispose all threads. // Dispose all threads.
const threadsCopy = this.threads.slice(); this.threads.forEach(thread => this._stopThread(thread));
while (threadsCopy.length > 0) {
const poppedThread = threadsCopy.pop();
this._removeThread(poppedThread);
}
} }
/** /**
@ -1114,6 +1106,10 @@ class Runtime extends EventEmitter {
} }
this.profiler.start(stepProfilerId); this.profiler.start(stepProfilerId);
} }
// Clean up threads that were told to stop during or since the last step
this.threads = this.threads.filter(thread => !thread.isKilled);
// Find all edge-activated hats, and add them to threads to be evaluated. // Find all edge-activated hats, and add them to threads to be evaluated.
for (const hatType in this._hats) { for (const hatType in this._hats) {
if (!this._hats.hasOwnProperty(hatType)) continue; if (!this._hats.hasOwnProperty(hatType)) continue;