mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-01-09 14:32:07 -05:00
Clean up yield-timers: support multiple, move logic to Threads.
This commit is contained in:
parent
578d02cba0
commit
190208b620
4 changed files with 34 additions and 38 deletions
|
@ -1,5 +1,3 @@
|
||||||
var YieldTimers = require('../util/yieldtimers.js');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set, block calls, args, and return values will be logged to the console.
|
* If set, block calls, args, and return values will be logged to the console.
|
||||||
* @const {boolean}
|
* @const {boolean}
|
||||||
|
@ -13,11 +11,6 @@ var execute = function (sequencer, thread) {
|
||||||
var currentBlockId = thread.peekStack();
|
var currentBlockId = thread.peekStack();
|
||||||
var currentStackFrame = thread.peekStackFrame();
|
var currentStackFrame = thread.peekStackFrame();
|
||||||
|
|
||||||
// Save the yield timer ID, in case a primitive makes a new one
|
|
||||||
// @todo hack - perhaps patch this to allow more than one timer per
|
|
||||||
// primitive, for example...
|
|
||||||
var oldYieldTimerId = YieldTimers.timerId;
|
|
||||||
|
|
||||||
var opcode = runtime.blocks.getOpcode(currentBlockId);
|
var opcode = runtime.blocks.getOpcode(currentBlockId);
|
||||||
|
|
||||||
// Generate values for arguments (inputs).
|
// Generate values for arguments (inputs).
|
||||||
|
@ -64,17 +57,12 @@ var execute = function (sequencer, thread) {
|
||||||
done: function() {
|
done: function() {
|
||||||
sequencer.proceedThread(thread);
|
sequencer.proceedThread(thread);
|
||||||
},
|
},
|
||||||
timeout: YieldTimers.timeout,
|
timeout: thread.addTimeout.bind(thread),
|
||||||
stackFrame: currentStackFrame,
|
stackFrame: currentStackFrame,
|
||||||
startSubstack: function (substackNum) {
|
startSubstack: function (substackNum) {
|
||||||
sequencer.stepToSubstack(thread, substackNum);
|
sequencer.stepToSubstack(thread, substackNum);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Update if the thread has set a yield timer ID
|
|
||||||
// @todo hack
|
|
||||||
if (YieldTimers.timerId > oldYieldTimerId) {
|
|
||||||
thread.yieldTimerId = YieldTimers.timerId;
|
|
||||||
}
|
|
||||||
if (DEBUG_BLOCK_CALLS) {
|
if (DEBUG_BLOCK_CALLS) {
|
||||||
console.log('ending stack frame: ', currentStackFrame);
|
console.log('ending stack frame: ', currentStackFrame);
|
||||||
console.log('returned: ', primitiveReturnValue);
|
console.log('returned: ', primitiveReturnValue);
|
||||||
|
|
|
@ -53,10 +53,10 @@ Sequencer.prototype.stepThreads = function (threads) {
|
||||||
// Normal-mode thread: step.
|
// Normal-mode thread: step.
|
||||||
this.startThread(activeThread);
|
this.startThread(activeThread);
|
||||||
} else if (activeThread.status === Thread.STATUS_YIELD) {
|
} else if (activeThread.status === Thread.STATUS_YIELD) {
|
||||||
// Yield-mode thread: check if the time has passed.
|
// Yield-mode thread: resolve timers.
|
||||||
if (!YieldTimers.resolve(activeThread.yieldTimerId)) {
|
activeThread.resolveTimeouts();
|
||||||
// Thread is still yielding
|
if (activeThread.status === Thread.STATUS_YIELD) {
|
||||||
// if YieldTimers.resolve returns false.
|
// Still yielding.
|
||||||
numYieldingThreads++;
|
numYieldingThreads++;
|
||||||
}
|
}
|
||||||
} else if (activeThread.status === Thread.STATUS_DONE) {
|
} else if (activeThread.status === Thread.STATUS_DONE) {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
var YieldTimers = require('../util/yieldtimers.js');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A thread is a running stack context and all the metadata needed.
|
* A thread is a running stack context and all the metadata needed.
|
||||||
* @param {?string} firstBlock First block to execute in the thread.
|
* @param {?string} firstBlock First block to execute in the thread.
|
||||||
|
@ -30,10 +32,10 @@ function Thread (firstBlock) {
|
||||||
this.status = 0; /* Thread.STATUS_RUNNING */
|
this.status = 0; /* Thread.STATUS_RUNNING */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Yield timer ID (for checking when the thread should unyield).
|
* Execution-synced timeouts.
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
this.yieldTimerId = -1;
|
this.timeoutIds = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,4 +106,29 @@ Thread.prototype.yield = function () {
|
||||||
this.status = Thread.STATUS_YIELD;
|
this.status = Thread.STATUS_YIELD;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an execution-synced timeouts for this thread.
|
||||||
|
* See also: util/yieldtimers.js:timeout
|
||||||
|
* @param {!Function} callback To be called when the timer is done.
|
||||||
|
* @param {number} timeDelta Time to wait, in ms.
|
||||||
|
*/
|
||||||
|
Thread.prototype.addTimeout = function (callback, timeDelta) {
|
||||||
|
var timeoutId = YieldTimers.timeout(callback, timeDelta);
|
||||||
|
this.timeoutIds.push(timeoutId);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to resolve all execution-synced timeouts on this thread.
|
||||||
|
*/
|
||||||
|
Thread.prototype.resolveTimeouts = function () {
|
||||||
|
var newTimeouts = [];
|
||||||
|
for (var i = 0; i < this.timeoutIds.length; i++) {
|
||||||
|
var resolved = YieldTimers.resolve(this.timeoutIds[i]);
|
||||||
|
if (!resolved) {
|
||||||
|
newTimeouts.push(this.timeoutIds[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.timeoutIds = newTimeouts;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = Thread;
|
module.exports = Thread;
|
||||||
|
|
|
@ -68,23 +68,4 @@ YieldTimers.resolve = function (id) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Reject a timer so the callback never executes.
|
|
||||||
* @param {number} id Timer ID to reject.
|
|
||||||
*/
|
|
||||||
YieldTimers.reject = function (id) {
|
|
||||||
if (YieldTimers.timers[id]) {
|
|
||||||
delete YieldTimers.timers[id];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reject all timers currently stored.
|
|
||||||
* Especially useful for a Scratch "stop."
|
|
||||||
*/
|
|
||||||
YieldTimers.rejectAll = function () {
|
|
||||||
YieldTimers.timers = {};
|
|
||||||
YieldTimers.timerId = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = YieldTimers;
|
module.exports = YieldTimers;
|
||||||
|
|
Loading…
Reference in a new issue