Hi, I found the term "display cycle" mentioned without a def in the most current version of the Reference Manual I've been able to find (for v4.1), in the following context
If several scripts that are visible in the scripting area are running at the same time, all of them are stepped in parallel. However, consider the case of two repeat loops with different numbers of blocks. While not stepping, each script goes through a complete cycle of its loop in each display cycle, despite the difference in the length of a cycle.
Can anyone comment on what a "display cycle" precisely is? Can code from more than one script execute within a given display cycle, and if so, how? Can anyone recommend some material(s) explaining how Snap! 5 scripts get CPU-scheduled in general, i.e., which sort of atomicity guarantees (that is, code guaranteed not to be interrupted by executing code from another script) one can rely on? WARP seems an easy example of an atomicity guarantee; based on the fragment above there seem to be others.
Yes, sorry, this should be better explained in the manual. Next pass...
So, there is no time slicing in Snap!'s scheduler; it works by explicit yields in scripts. The main rule is that a script yields at the bottom of any of the looping blocks. So if a sprite has two scripts, one saying FOREVER [MOVE 10 STEPS] and the other saying FOREVER [TURN 15 DEGREES], the result will be a perfect closed polygon (a near-circle), not a "drunken" one, because each script gets a turn in each cycle.
We talk about display cycles because usually the most time-consuming thing that happens in a scheduling cycle is refreshing the display: moving the sprites, drawing lines, updating the values in variable watchers, updating the direction of the sprite thumbnails in the sprite corral, and so on. So, each sprite runs once, then the display is updated, etc. It's as if the display were a script too.
The programmer can also yield on purpose by using a block with WAIT in its name; in particular, WAIT 0 SECONDS yields but makes the script immediately runnable without waiting.
Because there's no time-slicing, atomicity issues don't arise in most projects; you have to go out of your way to get in trouble. In particular, Snap! guarantees no yield between the test part of an IF and the running of the conditional code -- provided, of course, that that code doesn't yield immediately.
When we want to teach about atomicity, we have to write scripts with random probabilities of waiting explicit in the code. :~)
Fascinating. Thanks very much for the enlightening response. It's a pleasure to interact with people who not only build such a great body of code but also stay around to field random questions from us newbies.
Hi Ken, the answer I'd like to give is "no", we don't want users to think about the threading inside the protected atomic sections. However, the sequence in which the scripts are run is not really arbitrary, so, clever users have found out that you can prioritize one script over another by brining its (omg, I'm not really saying this, but here ya go) "layer" on top (the script you've last picked up and dropped with the mouse will be first to go). You can see why relying on this is probably a bad idea...
Without knowledge of threading internals it's hard to explain output of this script.
60 iterations (screen refresh rate) of empty loop took 1s. So literally every loop is slowed down to only one iteration per video frame. The same is true for calculation and sprite update scripts. It can lead to unexpected slow down not justified by script complexity and without processor load.
So every non UI script must be "warped" to get some decent performance. For not so trivial script it can be more suitable to run in "turbo" mode but there are no way to force screen updates on demand. Unfortunately "wait 0" doesn't work this way
"Everything first class" is aspirational; we're progressing slowly. First class costumes and sounds are new in 5.0.
As for scripts, we suffer from a paucity of language. The script, understood as a procedure, is first class, but you can't examine its innards; you can't, for example, ask for its arity (how many inputs it takes). But "script" also means the text of the script--the blocks that make it up. That's what I want to make first class, so you can, for example, look to see what procedures (blocks) it calls. My plan is to have two primitives converting back and forth between a script and a list structure that embodies the abstract syntax tree for the script. Then you can interrogate it with ordinary list operations.