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 javax.swing.*;
import java.awt.*;
import org.taj.ajava.lang.*;
public class AContainer extends AComponent
{
protected final Container container;
public AContainer(Container container)
{
super(container);
this.container = container;
}
public static class AddComponent
{
public AComponent value;
public int at = -1;
public AddComponent(AComponent value)
{
this.value = value;
}
public AddComponent(AComponent value, int at)
{
this(value);
this.at = at;
}
}
public class R1 extends org.taj.ajava.lang.Actor
{
int MSG_WAITING_COUNT;
R1(final AContainer THIS_LINK, final AddComponent add)
{
this.MSG_WAITING_COUNT = 0;
this.FORK_WAITING_COUNT = 1;
this.THIS_LINK = THIS_LINK;
this.add = add;
}
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 R2 extends org.taj.ajava.lang.Actor
{
Component c;
int MSG_WAITING_COUNT;
R2(final R1 OWNER_RECEPTIONIST)
{
this.MSG_WAITING_COUNT = 1;
this.OWNER_RECEPTIONIST = OWNER_RECEPTIONIST;
}
private void react_0(AComponent.ComponentAccessor.Response responseMessage)
{
switch (responseMessage.getRequestID()) {
case 0:
{
c = responseMessage.value;
this.MSG_WAITING_COUNT--;
break;
}
}
if (this.MSG_WAITING_COUNT <= 0) continuation();
}
public void deliver(AComponent.ComponentAccessor.Response responseMessage)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(responseMessage, 0));
}
protected void react(AComponent.ComponentAccessor.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
{
{
container.add(c, add.at);
}
}
finally
{
done();
}
}
R1 OWNER_RECEPTIONIST;
protected void processMessage(org.taj.ajava.runtime.ActorMessage msg)
{
switch (msg.reactorId) {
case 0:
{
react_0(((AComponent.ComponentAccessor.Response)msg.payload));
return;
}
case 1:
{
react_1(((org.taj.ajava.runtime.Continue)msg.payload));
return;
}
default:
{
super.processMessage(msg);
return;
}
}
}
}
void continuation()
{
{
{
{
R2 _R2 = new R2(this);
add.value.getComponent.deliver(AComponent.ComponentAccessor.Request.create(_R2, 0, new AComponent.ComponentAccessor.Get()));
}
}
}
}
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);
}
AContainer THIS_LINK;
AddComponent add;
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(AddComponent add)
{
blockActor();
{
R1 _R1 = new R1(this, add);
_R1.deliver(new org.taj.ajava.runtime.Continue());
}
}
public void deliver(AddComponent add)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(add, 0));
}
protected void react(AddComponent add)
{
react_0(add);
}
public static class RemoveComponent
{
public AComponent value;
public RemoveComponent(AComponent value)
{
this.value = value;
}
}
public class R3 extends org.taj.ajava.lang.Actor
{
int MSG_WAITING_COUNT;
R3(final AContainer THIS_LINK, final RemoveComponent rem)
{
this.MSG_WAITING_COUNT = 0;
this.FORK_WAITING_COUNT = 1;
this.THIS_LINK = THIS_LINK;
this.rem = rem;
}
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 R4 extends org.taj.ajava.lang.Actor
{
Component c;
int MSG_WAITING_COUNT;
R4(final R3 OWNER_RECEPTIONIST)
{
this.MSG_WAITING_COUNT = 1;
this.OWNER_RECEPTIONIST = OWNER_RECEPTIONIST;
}
private void react_0(AComponent.ComponentAccessor.Response responseMessage)
{
switch (responseMessage.getRequestID()) {
case 0:
{
c = responseMessage.value;
this.MSG_WAITING_COUNT--;
break;
}
}
if (this.MSG_WAITING_COUNT <= 0) continuation();
}
public void deliver(AComponent.ComponentAccessor.Response responseMessage)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(responseMessage, 0));
}
protected void react(AComponent.ComponentAccessor.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
{
{
container.remove(c);
}
}
finally
{
done();
}
}
R3 OWNER_RECEPTIONIST;
protected void processMessage(org.taj.ajava.runtime.ActorMessage msg)
{
switch (msg.reactorId) {
case 0:
{
react_0(((AComponent.ComponentAccessor.Response)msg.payload));
return;
}
case 1:
{
react_1(((org.taj.ajava.runtime.Continue)msg.payload));
return;
}
default:
{
super.processMessage(msg);
return;
}
}
}
}
void continuation()
{
{
{
{
R4 _R4 = new R4(this);
rem.value.getComponent.deliver(AComponent.ComponentAccessor.Request.create(_R4, 0, new AComponent.ComponentAccessor.Get()));
}
}
}
}
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);
}
AContainer THIS_LINK;
RemoveComponent rem;
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(RemoveComponent rem)
{
blockActor();
{
R3 _R3 = new R3(this, rem);
_R3.deliver(new org.taj.ajava.runtime.Continue());
}
}
public void deliver(RemoveComponent rem)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(rem, 1));
}
protected void react(RemoveComponent rem)
{
react_1(rem);
}
public static class ContainerAccessor extends Actor
{
private Container c;
public ContainerAccessor(Container c)
{
this.c = c;
}
public static class Get
{
}
private static class GetRequestMessage extends org.taj.ajava.runtime.ActorRequestMessage
{
public Get value;
public GetRequestMessage(final org.taj.ajava.lang.Actor rsvp, final int reqId)
{
super(rsvp, reqId);
}
}
private void react_0(GetRequestMessage requestMessage)
{
Get g = requestMessage.value;
{
Response responseMessage = new Response(requestMessage);
responseMessage.value = c;
requestMessage.sendReply(responseMessage);
return;
}
}
public void deliver(GetRequestMessage requestMessage)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(requestMessage, 0));
}
protected void react(GetRequestMessage requestMessage)
{
react_0(requestMessage);
}
public static class Request
{
public static GetRequestMessage create(final org.taj.ajava.lang.Actor rsvp, final int reqId, final Get value)
{
GetRequestMessage m = new GetRequestMessage(rsvp, reqId);
m.value = value;
return m;
}
}
public static class Response extends org.taj.ajava.runtime.ActorResponseMessage
{
public Container value;
private Response(final org.taj.ajava.runtime.ActorRequestMessage request)
{
super(request);
}
}
protected void processMessage(org.taj.ajava.runtime.ActorMessage msg)
{
switch (msg.reactorId) {
case 0:
{
react_0(((GetRequestMessage)msg.payload));
return;
}
default:
{
super.processMessage(msg);
return;
}
}
}
}
protected void processMessage(org.taj.ajava.runtime.ActorMessage msg)
{
switch (msg.reactorId) {
case 0:
{
react_0(((AddComponent)msg.payload));
return;
}
case 1:
{
react_1(((RemoveComponent)msg.payload));
return;
}
default:
{
super.processMessage(msg);
return;
}
}
}
}