JCoBox Tutorial

This is an introduction into the JCoBox language. JCoBox extends Java with new concurrency concepts, which make it much easier to write concurrent programs in Java. The concurrency concept is based on the actor-idea: instead of having threads that work on shared state, concurrency is expressed by concurrently running actors exchanging messages. An actor in JCoBox is a cobox. A cobox is a container for objects and for tasks. CoBoxes communicate via asynchronous method calls on objects of other coboxes.

Introduction

Hello World in JCoBox

Hello World in JCoBox looks exactly like the Java variant:

package helloworld;
class HelloWorld {
   public static void main(String... args) {
      System.out.println("Hello World");
   }
}

This is not surprising as the sequential part of JCoBox is mostly equivalent to Java. So every legal sequential Java code is in principle (with some exceptions explained below) also legal in JCoBox. As HelloWorld is only sequential, there is no need for using JCoBox at all.

Getting Concurrent

To make the example a little bit more interesting, we create a concurrent version of it. Concurrency in JCoBox is introduced by coboxes. CoBoxes can be seen as lightweight processes that have their own state and only communicate via asynchronous method calls with each other. Whenever a JCoBox program is started, it already runs in a cobox, namely the main cobox. For now, programming inside a cobox can be regarded to be purely sequential. To have some concurrency in our example, we need a second cobox. CoBoxes are created by instantiating cobox classes. A cobox class is a class that is annotated with the @CoBox annotation or that extends another cobox class. For our example, we write a cobox class Say with a single method say(String s) that prints out s. In the main method, we now create an instance of Say and asynchronously call the say method on that instance. Asynchronous method calls are indicated by an exclamation mark “!” instead of a dot. After the call, the main method prints out “World”:

package helloworld;
class HelloWorld2 {
   public static void main(String... args) {
      new Say() ! say("Hello ");
      System.out.print("World ");
   }
}

@CoBox class Say {
   void say(String s) {
       System.out.print(s);
   }
}

So does this program print “Hello World”? The answer is: sometimes. It either prints “Hello World” or “World Hello”. So what happens? The Say cobox that is created by the main method can be regarded as a separate process that runs independently from the main cobox. Invoking a method asynchronously on an object of another cobox schedules that call for eventual execution in the target cobox. The caller of an asynchronous method call, however, does not wait for the call to be completed. Instead it simply continues executing the subsequent code. An asynchronous method invocation can also be regarded as sending a message. So the main cobox sends a message to the Say cobox, but does not wait for the result and continues its execution by printing out “World”.

Say it all

We can modify the example by letting the Say cobox also print “World”:

package helloworld;
class HelloWorld3 {
   public static void main(String... args) {
      Say s = new Say();
      s ! say("Hello ");
      s ! say("World ");
   }
}

What will happen? Will it always print “Hello World”? The answer is: yes, because messages are ordered in JCoBox. This means that when messages are sent from one cobox to another, all messages will be executed in the same order as they are sent.

Say it in parallel

A final version of realizing our example is to use two Say coboxes, one for printing “Hello” and the other for printing “World”:

package helloworld;
class HelloWorld4 {
   public static void main(String... args) {
      new Say() ! say("Hello ");
      new Say() ! say("World ");
   }
}

This is now similar to the second version, because now two independent coboxes print the different strings. As a result, either “Hello World” or “World Hello” is printed. The ordering of messages does not help here, as ordering is only with respect to two coboxes. Messages sent to different coboxes are not in any ordering relation.

Futures

What if we want to ensure that a certain call is executed before we execute the next one? This can be done in JCoBox by waiting for the result of an asynchronous method call. For example, to ensure in the previous example, that the second say call is only send after the first has completed, we could wait for the result of the first call using await():

package helloworld;
class HelloWorld5 {
   public static void main(String... args) {
      new Say() ! say("Hello ") . await();
      new Say() ! say("World ");
   }
}

What exactly happens is that an asynchonous method call returns a future object and that await() is called on the future. A future is a place holder for the result of an asynchronous method call. A future can be in two states: unresolved or resolved. Initially, a future is in general unresolved. When the asynchronous method call has completed the future is resolved to the result of the call. Futures can only be resolved once. To read a future either the await() or the get() method is used. They slightly differ in their meaning, but for now it is enough to know that both methods wait until the future is resolved and then return the value of the previous call. Futures are objects of the interface Fut<V> where V is the type of its value. For example, we could write an Echo cobox with an echo method returning its argument

package helloworld;
class HelloWorld6 {
   public static void main(String... args) {
      Fut<String> fut = new Echo() ! echo("World ");
      System.out.print( "Hello " );
      System.out.print( fut.await() );
   }
}

@CoBox class Echo {
   String echo(String s) {
      return s;
   }
}

Synchronous Calls

to be written

Service Objects

to be written

Cooperative Multitasking

to be written

Promises

to be written

Transfer Classes

Immutable Classes

In principle, coboxes do not share any state. This guarantees that data-races can never happen. Sharing state, however, is safe if the referenced state is immutable. JCoBox supports this by allowing immutable objects to be shared between coboxes. An immutable object is an instance of an immutable class, which is a class that is annotated with @Immutable. The fields of immutable classes are implicitly final. In addition, it fields may not be of transfer classes, or of Object.

Example:

@Immutable class Point {
   int x;
   int y;
   Point(int x; int y) {
      this.x = x;
      this.y = y;
   }
}

GUI Programming

to be written