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 SortingBenchmark extends Actor implements Entrypoint
{
private static final int reptCount = 100;
private IntegerArray arrayA, arrayB, arrayC;
private long Da = 0, Db = 0, Dc = 0;
private IntSorter a;
private IntSorterThread b;
private void react_0(String[] args)
{
Stdout.getInstance().deliver("Sorting Benchmark\n");
arrayA = new IntegerArray(10000);
arrayB = new IntegerArray(10000);
arrayC = new IntegerArray(10000);
a = new IntSorter();
b = new IntSorterThread();
this.react(reptCount);
}
public void deliver(String[] args)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(args, 0));
}
protected void react(String[] args)
{
react_0(args);
}
public class R7 extends org.taj.ajava.lang.Actor
{
int MSG_WAITING_COUNT;
R7(final SortingBenchmark THIS_LINK, final int i)
{
this.MSG_WAITING_COUNT = 0;
this.FORK_WAITING_COUNT = 1;
this.THIS_LINK = THIS_LINK;
this.i = i;
}
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 R8 extends org.taj.ajava.lang.Actor
{
int MSG_WAITING_COUNT;
R8(final R7 OWNER_RECEPTIONIST)
{
this.MSG_WAITING_COUNT = 1;
this.OWNER_RECEPTIONIST = OWNER_RECEPTIONIST;
}
private void react_0(IntSorter.Response responseMessage)
{
switch (responseMessage.getRequestID()) {
case 0:
{
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;
Da += T;
T = System.currentTimeMillis();
b.sort(arrayB);
T = System.currentTimeMillis() - T;
Db += T;
T = System.currentTimeMillis();
SorterMethods.sortArray(arrayC);
T = System.currentTimeMillis() - T;
Dc += T;
if (i > 1) THIS_LINK.deliver(i - 1);
else end();
}
}
finally
{
done();
}
}
R7 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()
{
{
{
SorterMethods.seedArray(arrayA);
SorterMethods.copyArray(arrayA, arrayB);
SorterMethods.copyArray(arrayA, arrayC);
{
T = System.currentTimeMillis();
}
{
R8 _R8 = new R8(this);
a.deliver(IntSorter.Request.create(_R8, 0, arrayA));
}
}
}
}
long T;
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);
}
SortingBenchmark THIS_LINK;
int i;
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_1(int i)
{
blockActor();
{
R7 _R7 = new R7(this, i);
_R7.deliver(new org.taj.ajava.runtime.Continue());
}
}
public void deliver(int i)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(new Integer(i), 1));
}
protected void react(int i)
{
react_1(i);
}
void end()
{
System.out.print("Actors: ");
System.out.print(Da / reptCount);
System.out.println("ms");
System.out.print("Threads: ");
System.out.print(Db / reptCount);
System.out.println("ms");
System.out.print("Sequential: ");
System.out.print(Dc / reptCount);
System.out.println("ms");
}
protected void processMessage(org.taj.ajava.runtime.ActorMessage msg)
{
switch (msg.reactorId) {
case 0:
{
react_0(((String[])msg.payload));
return;
}
case 1:
{
react_1(((Integer)msg.payload).intValue());
return;
}
default:
{
super.processMessage(msg);
return;
}
}
}
private SortingBenchmark()
{
}
private static class SingletonHolder
{
private final static SortingBenchmark instance = new SortingBenchmark();
}
public static SortingBenchmark getInstance()
{
return SingletonHolder.instance;
}
}