Tutorial

English

Français

Concurrent programming

Goals:

Dynamicity

This example illustrates the ability to extend dynamically a running reactive system, by adding a new reactive component in parallel between two instants of execution.

Source: AddPrograms.java
import inria.meije.rc.sugarcubes.*;

public class AddPrograms
{
// This method builds a program made a sequence of println and stop with two
// parameters.
    public static Program makePrint(final int programNumber, final int start){
        return SC.seq(
                      SC.println(programNumber+": Hello World! at "+start)
                      ,SC.stop()
                      ,SC.seq(
                              SC.println(programNumber+": Hello World! at "+(start+1))
                              , SC.stop()
                              , SC.println(programNumber+": Hello World! at "+(start+2))
                              , SC.stop()
                              )
                      , SC.println(programNumber+": Hello World! at "+(start+3))
                      , SC.stop()
                      , SC.println(programNumber+": Hello World! at "+(start+4))
                      );
    }
    public static void main(final String[] args){
// One makes a reactive machine with a first program with number 1 and starting
// at the first instant.
        final Machine machine = SC.emptyMachine(makePrint(1,1));
        int i = 1;
// One adds a new program with number 2 ans still starting at instant 1
        machine.addProgram(makePrint(2,1));
        new{
            System.out.print((i++)+"-: ");
            if(3 == i){
// If i equals 2 one adds a new programwith number 3 and starting at instant 2
                machine.addProgram(makePrint(3,2));
            }
// If i equals 6 one adds a new programwith number 4 and starting at instant 6
            if(7 == i){
                machine.addProgram(makePrint(4,6));
            }
        }while(!machine.react());
    }
}

The method makePrint build a program identified by a number (which is used to highlight the corresponding output on the standard output). This example shows that each program added into the machine is executed in concurrently with other already running program.

One can also add multiple copies of a program using the method getCopy of the Program interface. It allows one to get an exact copy of a reactive program in order to add it in a reactive machine or to reuse a piece of code in a larger reactive program.

final Program p2 = p.getCopy();

This is required because reactive programs are not reentrant. That means two concurrent threads of execution cannot run concurently the same machine (react method). When one adds a program into a machine, while the program gets executed, the internal state of the program (the state of the instructions that are node of the program tree) is modified. So to avoid possible interferences between two concurrent executions of the same program, it is strongly recommended to make a copy of the program (even if actual implementation of the method addProgram in SugarCubes does a copy of each program added).

How to compile?

(Instructions provided for a UNIX system using JDK 1.1.x or higher version number).
javac -classpath SugarCubesv4.0.0a4.jar AddPrograms.java

How to execute?

java -classpath SugarCubesv4.0.0a4.jar:. AddPrograms

You should get the following result:

1-: 1: Hello World! at 1
2: Hello World! at 1
2-: 1: Hello World! at 2
2: Hello World! at 2
3: Hello World! at 2
3-: 1: Hello World! at 3
2: Hello World! at 3
3: Hello World! at 3
4-: 1: Hello World! at 4
2: Hello World! at 4
3: Hello World! at 4
5-: 1: Hello World! at 5
2: Hello World! at 5
3: Hello World! at 5
6-: 3: Hello World! at 6
4: Hello World! at 6
7-: 4: Hello World! at 7
8-: 4: Hello World! at 8
9-: 4: Hello World! at 9
10-: 4: Hello World! at 10

See also: Source: GetCopy.java


The Junior API

Source: Junior_AddPrograms.java
import junior.*;

public class Junior_AddPrograms
{
    public static void main(final String[] args){
// First one writes a reactive program.
        Program p = Jr.Seq(Jr.Print("Hello World! 1\n"),Jr.Stop());
        p = Jr.Seq(p,Jr.Seq(Jr.Print("Hello World! 2\n"),Jr.Stop()));
        p = Jr.Seq(p,Jr.Seq(Jr.Print("Hello World! 3\n"),Jr.Stop()));
        p = Jr.Seq(p,Jr.Seq(Jr.Print("Hello World! 4\n"),Jr.Stop()));
        
        Machine machine = Jr.Machine(p);
        for(int i = 1; i <= 10; i++){
            System.out.println("instant "+i+": ");
//Before reaction for the 3th instant one adds a copy of print into the machine.
            if(3 == i){ machine.add(p.copy()); }
//Before reaction for the 5th instant one adds a copy of print into the machine.
            if(5 == i){ machine.add(p.copy()); }
            machine.react();
        }
    }
}

How to compile?

(Instructions provided for a UNIX system using JDK 1.1.x or higher version number).
javac -classpath SugarCubesv4.0.0a4.jar Junior_AddPrograms.java

How to execute?

java -classpath SugarCubesv4.0.0a4.jar:. Junior_AddPrograms

You should get the following result:

instant 1: 
Hello World! 1
instant 2: 
Hello World! 2
instant 3: 
Hello World! 3
Hello World! 1
instant 4: 
Hello World! 4
Hello World! 2
instant 5: 
Hello World! 3
Hello World! 1
instant 6: 
Hello World! 4
Hello World! 2
instant 7: 
Hello World! 3
instant 8: 
Hello World! 4
instant 9: 
instant 10: 

Explicit Concurrency

This example shows how to handle concurrent components in a reactive system using the merge primitive.

Source: Concurrency.java
import inria.meije.rc.sugarcubes.*;

public class Concurrency
{
    public static void main(final String[] args){
        final Program p = SC.seq(
                           SC.println("Hello World! 1")
                           , SC.stop()
                           , SC.println("Hello World! 2")
                           , SC.stop()
                           , SC.println("Hello World! 3")
                           , SC.stop()
                           , SC.println("Hello World! 4")
                           , SC.stop()
                           );
        // One adds a program into a machine which uses 3 copies of
        // the program p in parallel. But the last one is delayed by
        // one instant due to a sequence with stop.
        final Machine machine = SC.machine(
                                     SC.merge(
                                              SC.merge(
                                                       p
                                                       , p.getCopy()
                                                       )
                                              , SC.seq(
                                                       SC.stop()
                                                       , p.getCopy()
                                                       )
                                              )
                                     );
        for(int i = 1; i <= 10; i++){
            System.out.println("instant "+i+": ");
            machine.react();
        }
    }
}

In this example one considers the merge instruction as a binary instruction. It takes two reactive programs and make them both progress for one instant at each instant. It simulates parallelism (but determinist one) by interleaving the execution of the branches during one instant.

SC.merge(p,p.getCopy())

The semantics of the merge instruction can be more precisely considered : during an instant it always actives the first branch until this one suspends its execution then it gives the control to the other branch, and do this cyclically until both branches reach the end of the instant. Concurrency in SugarCubes is handled in a deterministic manner by enforcing a choice in the way to handle interleaving. This has the great advantage to be deterministic even if the programmer hasn't a real idea of what the interleaving should be.

To combine multiple branch in parallel one builds a tree of multiple merge instructions.

How to compile?

(Instructions provided for a UNIX system using JDK 1.1.x or higher version number).
javac -classpath SugarCubesv4.0.0a4.jar Concurrency.java

How to execute?

java -classpath SugarCubesv4.0.0a4.jar:. Concurrency

You should get the following result:

instant 1: 
Hello World! 1
Hello World! 1
instant 2: 
Hello World! 2
Hello World! 2
Hello World! 1
instant 3: 
Hello World! 3
Hello World! 3
Hello World! 2
instant 4: 
Hello World! 4
Hello World! 4
Hello World! 3
instant 5: 
Hello World! 4
instant 6: 
instant 7: 
instant 8: 
instant 9: 
instant 10: 


The Junior API

Source: Junior_Parallelism.java
import junior.*;

public class Junior_Parallelism
{
    public static void main(final String[] args){
        Program p = Jr.Seq(Jr.Print("Hello World! 1\n"), Jr.Stop());
        p = Jr.Seq(p, Jr.Seq(Jr.Print("Hello World! 2\n"), Jr.Stop()));
        p = Jr.Seq(p, Jr.Seq(Jr.Print("Hello World! 3\n"), Jr.Stop()));
        p = Jr.Seq(p, Jr.Seq(Jr.Print("Hello World! 4\n"), Jr.Stop()));
        
        final Machine machine = Jr.Machine(
                                           Jr.Par(
                                                  Jr.Par(p, p.copy())
                                                  , Jr.Seq(
                                                           Jr.Stop()
                                                           , p.copy()
                                                           )
                                                  )
                                           );
        for(int i = 1; i <= 10; i++){
            System.out.println("instant "+i+": ");
            machine.react();
        }
    }
}

How to compile?

(Instructions provided for a UNIX system using JDK 1.1.x or higher version number).
javac -classpath SugarCubesv4.0.0a4.jar Junior_Parallelism.java

How to execute?

java -classpath SugarCubesv4.0.0a4.jar:. Junior_Parallelism