Tutorial

English

Français

Atomic Actions in Java

In this example one learns to build atomic actions. Atomic actions are the mechanism through which tasks described in Java are controlled by reactive programs.
Atomic actions are implemented by the programmer, implementing the interface JavaAction. Then, those actions are handled in a reactive program using the reactive instruction action. Atomic actions, as their name lets think, are not interruptible in SugarCubes, so it is the responsibility of the programmer to ensure that they terminate in a finite time (the shortest as possible). So, in general atomic actions must be very simple tasks in Java, without infinite loops (a good solution is often to avoid loops at all), that performs their actions very quickly. While scheduling (loops, ...) and control is handled by the reactive program itself.

Source: AtomicActions.java
import inria.meije.rc.sugarcubes.Machine;
import inria.meije.rc.sugarcubes.SC;
import inria.meije.rc.sugarcubes.Program;
import inria.meije.rc.sugarcubes.JavaAction;
import inria.meije.rc.sugarcubes.LocalVariables;
import inria.meije.rc.sugarcubes.ReactiveEngine;

class AtomicActions
{
    public static void main(String[] args){
// First one writes a reactive program.
        Program print = SC.action(new AtomExample());

// Then one makes a reactive execution machine.
        Machine machine = SC.machine();

// One adds the program into the machine.
        machine.addProgram(print);

// One makes the machine reacts for ten consecutive instants.
        for(int i = 1; i <= 10; i++){
            System.out.println("instant "+i+": ");
            machine.react();
        }
    }
}

class AtomExample implements JavaAction
{
    public void execute(Object self, LocalVariables vars, ReactiveEngine engine){
        System.out.println("This is an atomic action");
    }
}

One has to implement its atomic java action in a class that implements the JavaAction interface.

class AtomExample implements JavaAction

One puts the java code which describes the atomic action in the method execute. The meaning of the self, vars and engine parameter will be discussed later. They provide information on the context of execution for the atomic action.
To handle atomic actions in a reactive program one uses the action instruction, which execute the java code in an atomic way (not interruptible).

Program print = SC.action(new AtomExample());

The action instruction gets a JavaAction object as parameter. And invoke the execute method when it gets the control. SugarCubes doesn't do any verification on what the action really does. So it is the responsibility of the programmer to make the atomic action cooperative enough to terminate quickly (in a finite time). To get a good reactive system (that doesn't stale for a while at a point of its execution, preventing the whole system to progress), the programmer must ensure that its atomic actions are "reactive" enough (fast enough to ensure a good response time).
A bad atomic action could be a simple code like that:

class BadAtom implements JavaAction
{
    public void execute(Object self, LocalVariables vars, ReactiveEngine engine){
        for(;;);
    }
}

SugarCubes reactive machine assumes that atomic actions terminates in a finite amount of time and so to preserve the right semantics of execution no control (through heuristics on the duration of the execution of an atomic action fro example) is done. So, in this case, when the execute method of the BadAtom object get invoked, the control never return to the reactive execution machine, and so the overall system is staled.

The simplest atomic instruction that exist in SugarCubes is the instruction nothing which does ... nothing.

Program p = SC.nothing();

The print instruction, used in the HelloWorld example, is a shortcut for an atomic action which displays a message on the standard output. A similar instruction exists also to print a message on the standard error output.

Program p = SC.printError("Error: This is an error message\n");

How to compile?

javac -classpath SugarCubesv3.1.0.jar AtomicActions.java

How to execute?

java -classpath SugarCubesv3.1.0.jar:. AtomicActions

You should get the following result:

instant 1: 
This is an atomic action
instant 2: 
instant 3: 
instant 4: 
instant 5: 
instant 6: 
instant 7: 
instant 8: 
instant 9: 
instant 10: 

Atomic actions with the Junior API

One considers now the same example but using the Junior API.

Source: Junior_AtomicActions.java
import junior.Machine;
import junior.Jr;
import junior.Program;
import junior.Action;
import junior.Environment;

class Junior_AtomicActions
{
    public static void main(String[] args){
// First one writes a reactive program.
        Program print = Jr.Atom(new Junior_AtomExample());

// Then one makes a reactive execution machine.
        Machine machine = Jr.Machine(print);

// One makes the machine reacts for ten consecutive instants.
        for(int i = 1; i <= 10; i++){
            System.out.println("instant "+i+": ");
            machine.react();
        }
    }
}

class Junior_AtomExample implements Action
{
    public void execute(Environment env){
        System.out.println("This is an atomic action");
    }
}

How to compile?

javac -classpath SugarCubesv3.1.0.jar Junior_AtomicActions.java

How to execute?

java -classpath SugarCubesv3.1.0.jar:. Junior_AtomicActions

Sequence:

This example illustrates the use of the sequence primitive. During one instants, one puts atomic actions (print actions in this case) in sequence.

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

class Sequence
{
    public static void main(String[] args){
        Program p = SC.seq(
                            SC.print("Hello World!\n")
                            ,SC.print("This program shows ")
                            ,SC.print("sequences ")
                            ,SC.print("of printed ")
                            ,SC.print("messages!\n")
                            );

        Machine machine = SC.emptyMachine(p);
        int i = 1;
        do{
            System.out.println("instant "+(i++)+": ");
        }
        while(!machine.react());
    }
}

The react method of a reactive machine returns a boolean value which is false while the program is not terminated and true when the program terminates. To be able to use this capability, one must create an empty execution machine using the emptyMachine variant in the SC class. The diference between machine and emptyMachine is that the first one variants are constructing machines that put a halt instruction in parallel to any program, leading to machines with a program that can never end. In this example one uses this value to know when to stop cyclic calls to the react method.

How to compile?

javac -classpath SugarCubesv3.1.0.jar Sequence.java

How to execute?

java -classpath SugarCubesv3.1.0.jar:. Sequence

One should get the following result:

        instant 1: 
        Hello World!
        This program shows sequences of printed messages!

Using the Junior API

Source: Junior_Sequence.java
import junior.*;

class Junior_Sequence
{
    public static void main(String[] args){
        // The Junior interface of SugarCubes only provides binary sequence primitive.
        Program print = Jr.Seq(
                    Jr.Print("Hello World!\n")
                    ,Jr.Seq(
                        Jr.Print("This program shows ")
                        ,Jr.Seq(
                            Jr.Print("sequences ")
                            ,Jr.Seq(
                                Jr.Print("of printed ")
                                ,Jr.Print("messages!\n")
                            )
                        )
                    )
                );

        Machine machine = Jr.Machine(Jr.Nothing());

        machine.add(print);

        int i = 1;
        do{
            System.out.println("instant "+(i++)+": ");
        }
        while(!machine.react());
    }
}

How to compile?

javac -classpath SugarCubesv3.1.0.jar Junior_Sequence.java

How to execute?

java -classpath SugarCubesv3.1.0.jar:. Junior_Sequence