6.1 Simple coroutines

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.

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.

Hello world