19 Concurrent Library

Concurrent programming in BETA is supported by the systemenv library. This library contains patterns for describing the BETA concepts of concurrent systems. The basic ideas are:

19.1 18.1 Example

The following example of using the systemenv library makes three concurrent coroutines that each sleeps for a specified number of seconds and then prints out the seconds elapsed since startup. All three systems inherit from a generic system:

everyNthSecond: System
  (* inherit from System: can run concurrently *)
  (# N:< IntegerValue;
     now: @Integer;
  do cycle 
       (# 
       do INNER everyNthSecond;
          N -> sleep; (* sleep for N seconds *)
          now+N -> now; (* accumulate time *)
       #)
  #)

everyNthSecond inherits from system, i.e. it is able to run concurrently. The do-part consists of a loop that calls INNER, then sleeps for N seconds, and when activated again, updates the time, and calls INNER again. Notice, that N is defined as an IntegerValue.

Now we can make a coroutine that inherits from everyNthSecond like this:

fourth: @| everyNthSecond
       (* a co-routine that inherits from everyNthSecond *)
  (# N:: (# do 4 -> value #); (* sleep for 4 seconds *)
  do 'fourth: ' -> puttext; now -> screen.putint; newline
  #)

A coroutine is declared using the '|' symbol. The declaration '@|' means that we declare fourth to be a static reference to a coroutine. The do-part will be called every 4'th second since fourth inherits from everyNthSecond and extends the IntegerValue N to be 4.

Finally, we need to start the coroutines concurrently. This is done by starting the coroutine inside a conc pattern like this:

conc (* execute concurrently: *)
  (# do ... fourth[]->start; ... #)

The execution of conc will not terminate until all the systems executed inside it has terminated.

The complete program with three concurrent systems is shown in Program 18.1. Notice, that the program never terminates.

Program 26: Seconds.bet

ORIGIN '~beta/basiclib/systemenv'
--- program: descriptor ---
systemEnv (* inherits from systemEnv *)
(# 
   (* everyNthSecond calls INNER every Nth second. *)
   everyNthSecond: System (* Inherit from System: can run concurrently *)
     (# N:< IntegerValue;
        now: @Integer;
     do cycle 
          (# 
          do INNER everyNthSecond;
             N -> sleep; (* sleep for N seconds *)
             now+N -> now; (* accumulate time *)
          #);
     #);
   every: @| everyNthSecond (* a co-routine that inherits from everyNthSecond *)
     (# N::< (# do 1 -> value #);  (* sleep for 1 second *)
     do 'every: ' -> putText; now -> screen.putInt; newline;
     #);
   fourth: @| everyNthSecond (* a co-routine that inherits from everyNthSecond *)
     (# N::< (# do 4 -> value #); (* sleep for 4 seconds *)
     do 'fourth: ' -> putText; now -> screen.putInt; newline;
     #);
   eigth: @| everyNthSecond (* a co-routine that inherits from everyNthSecond *)
     (# N::< (# do 8 -> value #); (* sleep for 8 seconds *)
     do 'eigth: ' -> putText; now -> screen.putInt; newline;
     #);
do
   (* execute concurrently: *)
   conc (# do every[] -> start; fourth[] -> start; eigth[] -> start; #);
   (* terminates when all systems stops *)
#)

Output of running Program 18.1 for 20 seconds:

nil% Seconds
every: 0
fourth: 0
eighth: 0
every: 1
every: 2
every: 3
fourth: 4
every: 4
every: 5
every: 6
every: 7
eighth: 8
fourth: 8
every: 8
every: 9
every: 10
every: 11
fourth: 12
every: 12
every: 13
every: 14
every: 15
eighth: 16
fourth: 16
every: 16
every: 17
every: 18
every: 19
fourth: 20


Libraries Tutorial
© 1994-2002 Mjølner Informatics
[Modified: Thursday October 19th 2000 at 14:10]