Previous: Storing counter values, Up: Counter and timer statements [Contents][Index]
Counters can be restored to their most recently saved values with a <restore_stmt>:
<restore_stmt> | ::= | <source_task> |
RESTORES ITS
COUNTERS |
For example, writing ‘TASKS t SUCH THAT 3 DIVIDES t
RESTORE THEIR COUNTERS’ causes every third task to replace
elapsed_usecs
,
total_msgs
, bit_errors
, etc. with the
values stored by a corresponding <store_stmt> (see
Storing
counter values). Note that ITS
and
THEIR
, like RESTORE
and
RESTORES
, are considered synonyms (see Primitives).
An important feature of STORES
and RESTORES
is
that they can be nested. That is, each STORE
pushes a set of counter
values on a stack, and each RESTORE
pops a set of counter
values from the stack. Consequently, one can write code like the
following:
ALL TASKS RESET THEIR COUNTERS THEN # 1 ALL TASKS COMPUTE FOR 2 SECONDS THEN # 2 ALL TASKS STORE THEIR COUNTERS THEN # 3 ALL TASKS COMPUTE FOR 5 SECONDS THEN # 4 ALL TASKS STORE THEIR COUNTERS THEN # 5 ALL TASKS COMPUTE FOR 9 SECONDS THEN # 6 ALL TASKS LOG ROUND(elapsed_usecs/1E6) AS "Should be 16" THEN # 7 ALL TASKS RESTORE THEIR COUNTERS THEN # 8 ALL TASKS LOG ROUND(elapsed_usecs/1E6) AS "Should be 7" THEN # 9 ALL TASKS STORE THEIR COUNTERS THEN # 10 ALL TASKS COMPUTE FOR 1 SECOND THEN # 11 ALL TASKS LOG ROUND(elapsed_usecs/1E6) AS "Should be 8" THEN # 12 ALL TASKS RESTORE THEIR COUNTERS THEN # 13 ALL TASKS LOG ROUND(elapsed_usecs/1E6) AS "Should be 7" THEN # 14 ALL TASKS RESTORE THEIR COUNTERS THEN # 15 ALL TASKS LOG ROUND(elapsed_usecs/1E6) AS "Should be 2". # 16 |
Indentation is used in the above to clarify which RESTORE
operations match which STORE
operations. The first
STORE
statement (line 3) occurs after 2 seconds
have elapsed. The second STORE
statement (line 5)
occurs after 2+5=7 seconds
have elapsed. When the
LOG
statement in line 7 is executed,
it reports that 2+5+9=16 seconds
have elapsed. The RESTORE
statement in
line 8 then “winds back the clock” to the previous
STORE
statement, the one in line 5. The next LOG
statement
(line 9) executes as if lines 5–8
never ran and therefore reports that only
2+5=7 seconds have elapsed. The LOG
statement in
line 12 sees an additional second of elapsed time
due to line 11’s COMPUTE
statement, for a total
of 2+5+1=8 seconds. However, the RESTORE
in
line 13 makes it as if that COMPUTE
never happened. Consequently, the LOG
statement in line 14
reports that only 2+5=7 seconds
have elapsed. Finally, the RESTORE
in line 15
sets the timer to the value it had all the way back at
line 3. The final LOG
statement (line 16
) therefore reports that only 2 seconds
have elapsed because line 2 contains
the only
COMPUTE
statement whose execution time has not been
discarded.
Because the
interpret
backend and those derived from it use
logical time instead of physical time, the code listed above will
report all zeroes. Replacing
‘ROUND(elapsed_usecs/1E6)’ with just
‘elapsed_usecs’ will log the logical times
{6,5,8,7,3}. That is, the LOG
statement in line 7
sees six events after the initial RESET
;15 the LOG
statement in line 9
sees only five events after the RESET
(corresponding to
lines 2, 3, 4, 5, and 9); and so
forth up to the final
LOG
statement, which sees only three events: those
produced by lines 2, 3, and 16
.
A program that calls RESTORE
more times than it
calls
STORE
will abort with a fatal run-time error.
Each statement in the example corresponds to a single event and therefore counts as one unit of time.
Previous: Storing counter values, Up: Counter and timer statements [Contents][Index]