Execution of a coroutine object may be suspended by executing the suspend statement.
Consider
Sys: obj
CoObj: obj
foo:
S1
CoObj.suspend
S3
CoObj.suspend
S5
foo
S2
CoObj.resume
S4
CoObj.resume
S6
When CoObj
is executed (happens when CoObj
is generated) as part of the execution/generation of Sys
), CoObj
starts by executing the pattern foo – foo then executes S1 followed by CoObj.suspend, which temporarily suspends execution of CoObj and returns to Sys.
Sys then executes S2 followed by CoObj.resume, which implies that execution of CoObj is resumed and S3 is executed.
Then CoObj.suspend is executed, returning to Sys, which executes S4 followed by CoObj.resume, implying that S5 is executed.
Then foo and CoObj terminate and control returns to Sys, which executes S6.
Example
Here we present an example of a simple coroutines n the form of a TrafficLight
.
TrafficlightSystem: obj
TrafficLight:
Red: = 0
Green: = 1
state: var integer
cycle
state:= Red
this(TrafficLight).suspend
state := Green
this(TrafficLight).suspend
northSouth: obj TrafficLight -- initially Red
eastWest: obj TrafficLight -- Initially Red
northSouth.resume -- now Green
cycle
sleep(100) -- keep the current lights for some time
eastWest.resume -- switch the lights
northSouth.resume
The TrafficlightSystem
contains two lights, northSouth
and eastWest
and it alternates between changing the directions of Red and Green.
(For here we ignore that for a short moment, that both lights may be Green at the same time.)
Coroutine with parameters
When resuming a coroutine, it may be desirable to be able to add parameters and return values that differ from the ones supplied when instantiating the coroutine. The example below, shows how this may be done.
The module CoArg defines a pattern RockMe – RockMe has an argument, S of type String and returns a reference (by default) to the RocMe object being generated.
A RockMe object suspends its execution after having executed S.print.
CoArg declares an object F being an instance of RockMe with “Jimmy” as the actual parameter.
The local pattern, doResume, of RockMe has an argument T of type String and returns an integer V. Execution of doResume resumes execution of the actual RockMe object.
The CoArg module has three invocations of F.doResume with different actual parameters and a new return value per execution.
The output from an execution of CoArg is:
Jimmy
Jimmy Hendrix 14
Jimmy Hendrix plays 20
Jimmy Hendrix plays the guitar 31
CoArg: obj
%include LIB.String
RockMe(S: ref String):
doResume(T: ref String) -> V: var integer:
S := S + T
this(RockMe).resume
V := S.length
loop: obj
S.print
this(RockMe).suspend
restart(loop)
N: var integer
F: = RockMe("Jimmy ")
newline
N := F.doResume("Hendrix ")
putint(N)
newline
N := F.doResume("plays ")
putint(N)
newline
N := F.doResume("the guitar ")
putint(N)
newline
Note! The above example is only meant to illustrate how to define parameters for resuming a coroutine. The example is easily made without using a coroutine. Coroutines are useful when the state of execution should be saved between invocations of pattern attributes. Such examples will be supplied.