I’m a swiss Master student in Computer Science. I’m very interested in C++, open source projects, Linux, Intel Assembly and Agile. I'm currently working on Eddi, a new programming language that I created to improve my skills in C++. I've also worked a lot on Java technologies (Sprint, Osgi, Play!, ...), but I'm not currently working with Java anymore. Baptiste is a DZone MVB and is not an employee of DZone and has posted 51 posts at DZone. You can read more from them at their website. View Full User Profile

Introduction to the JR Programming Language

06.29.2010
| 7097 views |
  • submit to reddit

JR is a programming language especially created to solve concurrent programming problems. This language extends Java, adding the main paradigms of concurrent programming. Moreover JR makes the concepts implemented in Java like process or semaphores easier. There are also several extensions for JR to add more functionality like monitors and Conditional Critical Region (CCR). JR is the implementation of the SR language for Java. JR just adds a layer over Java. Once we use the JR compiler, the JR source files are transformed into Java files and are executed by the virtual machine like any other Java class.

JR is often used as a school support to learn concurrent programming. In this article, we will see the basis of programming with JR. The presented version is from June 2009,  version 2.00602 which is based on Java 6.0.

This article needs you to have installed the JR environment on your system. An article is available here for the installation under Windows.

In this article, we will especially focus on the parts of the JR language for  concurrent programming. We will not see the the integrality of the language. JR has other benefits than to make concurrent programming easier, but we will not see that in this article. Moreover, all the aspects of concurrent programming in JR will not be treated here.

Hello World

Like all other languages, we must start with a simple Hello World. Thus we’ll create a file Hello.jr. Nothing special here, it’s pure Java :

public class Hello {
public static void main(String[] args){
System.out.println("Hello World");
}
}

Then we can compile it :

jrc Hello.jr

This will create a jrGen folder containing Java files. The result of a JR compilation is always a set of Java files corresponding to the translation of the JR files.

To launch your JR program, use the jr command followed by the name of the main class (class containing the main method) :

jr Hello

That will display :

Hello World

The jr command will also launch the compilation of Java files. This compilation will be done every time. If you want to make only the launch of compiled files, you can use the jrrun command.

Like said in introduction, the JR language extends the Java language. So, you can code in Java with JR. Thus an Hello World is only Java.

Processes

The first thing to see is the declaration of processes. This is done in an easier way than in Java. No need to instanciate some objects, this is done in a declarative way and JR make the rest.

For the declaration of process, JR introduce a new keyword process who enable to declare a process. Here is the simplest declaration of a process :

process Hello {
System.out.println("Processus");
}

Like you can see it, it’s easier than in Java. And better, no need to launch it, you just have to instantiate the class. A process can also be declared static. This time it will not be launched at the instantiation of the class but at the resolution of the class by the virtual machine. By example, we can rewrite an HelloWorld in that way :

public class HelloProcess {
static process Hello {
System.out.println("Hello World");
}

public static void main(String[] args){}
}

which displays exactly the same thing as the first version of  Hello World. The difference is that our display is made from a thread.

Moreover, JR enables you to declare a big set of threads in a declaration with the following syntax :

static process Hello((int id = 0; id < n; id++)){}

This will declare n threads. The syntax is the same as the for loop. Let’s declare 25 threads Hello World :

public class HelloProcess {
static process Hello((int id = 0; id < 25; id++)){
System.out.println("Hello World from thread " + id);
}

public static void main(String[] args){}
}

When we launch that, we could have the following result :

Hello World from thread 2
Hello World from thread 24
Hello World from thread 11
Hello World from thread 22
Hello World from thread 0
Hello World from thread 4
Hello World from thread 6
Hello World from thread 8
Hello World from thread 10
Hello World from thread 12
Hello World from thread 14
Hello World from thread 16
Hello World from thread 18
Hello World from thread 20
Hello World from thread 23
Hello World from thread 21
Hello World from thread 19
Hello World from thread 17
Hello World from thread 15
Hello World from thread 13
Hello World from thread 9
Hello World from thread 7
Hello World from thread 5
Hello World from thread 3
Hello World from thread 1

Like you can see, if you launch the program several times the display is not the same and the message comes in a completely different order at each launch. Nothing can guarantee the order the threads launches and still less the order of the execution of the instructions and you must not count on it.
It’s the basis of the concurrent programming. You cannot predict the order of the instructions in the different threads.

Quiescence action

JR introduces a new, powerful concept: the quiescence action. It’s an action that's executed when the system is quiescent. It seems that all the process are finished or remain in deadlocks.

Before that, we used to introduce the concept of operations. In our case, an operation is a simple method declared with the op keyword. But in JR an operation is more than a method and could be invoked in different ways and permit other things that methods, but this is beyond the scope of this article.

Here is a declaration of a simple operation.

public static op void end(){
System.out.println("End");
}

So, this is a simple method with the op prefix. You can invoke it like any other method. But you can also declare it like the action to execute when the system is in quiescence state. If we take our example of the 25 hello world and if we define the quiescence action here is what we get :

import edu.ucdavis.jr.JR;

public class QuiescenceProcess {
static process Hello((int id = 0; id < 25; id++)){
System.out.println("Hello World from thread " + id);
}

public static void main(String[] args){
try {
JR.registerQuiescenceAction(end);
} catch (edu.ucdavis.jr.QuiescenceRegistrationException e){
e.printStackTrace();
}
}

public static op void end(){
System.out.println("End");
}
}

We use the registerQuiescenceAction(op) method of the JR class. This class provide some utility methods for the JR programs
And a launch, we see something like that :

Hello World from thread 0
Hello World from thread 22
Hello World from thread 23
Hello World from thread 21
Hello World from thread 24
Hello World from thread 20
Hello World from thread 19
Hello World from thread 18
Hello World from thread 17
Hello World from thread 16
Hello World from thread 15
Hello World from thread 14
Hello World from thread 13
Hello World from thread 12
Hello World from thread 11
Hello World from thread 10
Hello World from thread 9
Hello World from thread 8
Hello World from thread 7
Hello World from thread 6
Hello World from thread 5
Hello World from thread 4
Hello World from thread 3
Hello World from thread 2
Hello World from thread 1
End

This is really useful to execute an action after the end of the system and verify something on the system. By example, display a message in the case of a deadlock or display debug informations on the executed operations.

 

 

Published at DZone with permission of Baptiste Wicht, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)