Previous: , Up: Counter and timer statements   [Contents][Index]


4.6.3 Restoring counter values

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.


Footnotes

(15)

Each statement in the example corresponds to a single event and therefore counts as one unit of time.


Previous: , Up: Counter and timer statements   [Contents][Index]

Scott Pakin, pakin@lanl.gov