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 Calculator extends AFrame
{
final ALU alu;
final NumberBox display;
final ADigitPad digitPad;
final AOpPad opPad;
public Calculator()
{
super("Calculator");
frame.setSize(300, 200);
this.deliver(new SetCloseOperation(SetCloseOperation.EXIT_ON_CLOSE));
alu = new ALU();
APanel panel = new APanel();
contentPane.deliver(new AContainer.AddComponent(panel));
display = new NumberBox();
display.OnOperation.deliver(new Event.Subscribe(alu));
alu.OnResult.deliver(new Event.Subscribe(display));
panel.deliver(new AContainer.AddComponent(display));
digitPad = new ADigitPad();
digitPad.OnClick.deliver(new Event.Subscribe(display));
panel.deliver(new AContainer.AddComponent(digitPad));
opPad = new AOpPad();
opPad.OnClick.deliver(new Event.Subscribe(this));
panel.deliver(new AContainer.AddComponent(opPad));
OnKeyTyped.deliver(new Event.Subscribe(this));
digitPad.OnKeyTyped.deliver(new Event.Subscribe(this));
opPad.OnKeyTyped.deliver(new Event.Subscribe(this));
}
private void react_3(char op)
{
if (validOperator(op)) {
display.deliver(new Operation(op));
}
}
public void deliver(char op)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(new Character(op), 3));
}
protected void react(char op)
{
react_3(op);
}
private void react_4(KeyboardEvent e)
{
if (Character.isDigit(e.character) || e.character == '.') {
display.deliver(e.character);
}
else if (e.character == '\r' || e.character == '\n') this.react('=');
else this.react(e.character);
}
public void deliver(KeyboardEvent e)
{
bufferMessage(new org.taj.ajava.runtime.ActorMessage(e, 4));
}
protected void react(KeyboardEvent e)
{
react_4(e);
}
public class Operation
{
public char operator;
public double operand;
public Operation(char op)
{
this.operator = op;
}
}
private static boolean validOperator(char c)
{
switch (c) {
case '+':
case '-':
case '*':
case '/':
case '^':
case '=':
{
return true;
}
default:
{
return false;
}
}
}
protected void processMessage(org.taj.ajava.runtime.ActorMessage msg)
{
switch (msg.reactorId) {
case 3:
{
react_3(((Character)msg.payload).charValue());
return;
}
case 4:
{
react_4(((KeyboardEvent)msg.payload));
return;
}
default:
{
super.processMessage(msg);
return;
}
}
}
}