Copyright Tristan Aubrey-Jones May 2008.
Abstract: A project investigating and developing an implicitly concurrent programming language, based on a metaphor taken from the physical world is reported. Uses a programming paradigm where programs consist of systems of autonomous agents, or active objects which communicate via message passing. A language enhancing Java with actors and linear types is presented. Example programs are written, compiled, and executed to evaluate the usefulness of the language. The language found to provide a familiar notation for implicit parallelism, and a compelling new model for concurrency, combining the performance of shared variables with the elegance of message passing.
Introductory Slides (PDF),
Report (PDF),
ActiveJava compiler prototype (ajavac),
ActiveJava runtime library (ajava_lang).
Examples:
calc - pocket calculator actor program dining - dining philosophers actor program (never deadlocks) sort - parallel quicksort implementation ("SortBenchmark" sorts 10,000 random integers using actors, java threads, and sequentially and compares)To compile examples use:
compile.bat ./calc compile.bat ./sort compile.bat ./diningTo run examples use:
run ./calc Main run ./dining Main run ./dining Main fast run ./sort Main run ./sort SortingBenchmark
import org.taj.ajava.util.*;
import org.taj.ajava.lang.*;
public class Main extends Actor implements Entrypoint
{
public class R5 extends org.taj.ajava.lang.Actor
{
int MSG_WAITING_COUNT;
R5(final Main THIS_LINK, final String[] args)
{
this.MSG_WAITING_COUNT = 0;
this.FORK_WAITING_COUNT = 1;
this.THIS_LINK = THIS_LINK;
this.args = args;
}
private void react_0(org.taj.ajava.runtime.Continue doContinuationMessage)
{
continuation();
}
public void deliver(org.taj.ajava.runtime.Continue doContinuationMessage)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(doContinuationMessage, 0));
}
protected void react(org.taj.ajava.runtime.Continue doContinuationMessage)
{
react_0(doContinuationMessage);
}
void done()
{
THIS_LINK.deliver(new org.taj.ajava.runtime.UnblockActor());
}
public class R6 extends org.taj.ajava.lang.Actor
{
int MSG_WAITING_COUNT;
R6(final R5 OWNER_RECEPTIONIST)
{
this.MSG_WAITING_COUNT = 1;
this.OWNER_RECEPTIONIST = OWNER_RECEPTIONIST;
}
private void react_0(IntSorter.Response responseMessage)
{
switch (responseMessage.getRequestID()) {
case 0:
{
array = responseMessage.value;
this.MSG_WAITING_COUNT--;
break;
}
}
if (this.MSG_WAITING_COUNT <= 0) continuation();
}
public void deliver(IntSorter.Response responseMessage)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(responseMessage, 0));
}
protected void react(IntSorter.Response responseMessage)
{
react_0(responseMessage);
}
private void react_1(org.taj.ajava.runtime.Continue doContinuationMessage)
{
continuation();
}
public void deliver(org.taj.ajava.runtime.Continue doContinuationMessage)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(doContinuationMessage, 1));
}
protected void react(org.taj.ajava.runtime.Continue doContinuationMessage)
{
react_1(doContinuationMessage);
}
void done()
{
OWNER_RECEPTIONIST.deliver(new org.taj.ajava.runtime.ForkDone());
}
void continuation()
{
try
{
{
t = System.currentTimeMillis() - t;
Stdout.getInstance().deliver(Long.toString(t));
SorterMethods.printArray(array);
}
}
finally
{
done();
}
}
R5 OWNER_RECEPTIONIST;
protected void processMessage(org.taj.ajava.runtime.ActorMessage msg)
{
switch (msg.reactorId) {
case 0:
{
react_0(((IntSorter.Response)msg.payload));
return;
}
case 1:
{
react_1(((org.taj.ajava.runtime.Continue)msg.payload));
return;
}
default:
{
super.processMessage(msg);
return;
}
}
}
}
void continuation()
{
{
{
if (args.length > 0) Stdout.getInstance().deliver("Hello " + args[0] + "!");
else Stdout.getInstance().deliver("Hello World!");
{
array = new IntegerArray(10000);
}
SorterMethods.seedArray(array);
{
t = System.currentTimeMillis();
}
{
sorter = new IntSorter();
}
{
R6 _R6 = new R6(this);
sorter.deliver(IntSorter.Request.create(_R6, 0, array));
}
}
}
}
IntegerArray array;
long t;
IntSorter sorter;
int FORK_WAITING_COUNT;
private void react_1(org.taj.ajava.runtime.ForkDone responseMessage)
{
FORK_WAITING_COUNT--;
if (FORK_WAITING_COUNT <= 0) done();
}
public void deliver(org.taj.ajava.runtime.ForkDone responseMessage)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(responseMessage, 1));
}
protected void react(org.taj.ajava.runtime.ForkDone responseMessage)
{
react_1(responseMessage);
}
Main THIS_LINK;
String[] args;
protected void processMessage(org.taj.ajava.runtime.ActorMessage msg)
{
switch (msg.reactorId) {
case 0:
{
react_0(((org.taj.ajava.runtime.Continue)msg.payload));
return;
}
case 1:
{
react_1(((org.taj.ajava.runtime.ForkDone)msg.payload));
return;
}
default:
{
super.processMessage(msg);
return;
}
}
}
}
private void react_0(String[] args)
{
blockActor();
{
R5 _R5 = new R5(this, args);
_R5.deliver(new org.taj.ajava.runtime.Continue());
}
}
public void deliver(String[] args)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(args, 0));
}
protected void react(String[] args)
{
react_0(args);
}
protected void processMessage(org.taj.ajava.runtime.ActorMessage msg)
{
switch (msg.reactorId) {
case 0:
{
react_0(((String[])msg.payload));
return;
}
default:
{
super.processMessage(msg);
return;
}
}
}
private Main()
{
}
private static class SingletonHolder
{
private final static Main instance = new Main();
}
public static Main getInstance()
{
return SingletonHolder.instance;
}
}