ActiveJava

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 ./dining
To run examples use:
run ./calc Main
run ./dining Main
run ./dining Main fast
run ./sort Main
run ./sort SortingBenchmark

Table.java

home Home   up Up   ( Download )


import org.taj.ajava.lang.*; public class Table extends Actor { private Clock clk; private int numPlaces; private Fork[] forks; private Philosopher[] diners; private int[] states; public Table(Clock clk, int numPlaces) { this.clk = clk; this.numPlaces = numPlaces; this.forks = new Fork[numPlaces]; this.diners = new Philosopher[numPlaces]; this.states = new int[numPlaces]; createPlace(numPlaces - 1); } private void createPlace(int index) { forks[index] = new Fork(index); diners[index] = new Philosopher(this, index); clk.subscribe(diners[index]); states[index] = State.THINKING; if (index > 0) createPlace(index - 1); } private int left(int id) { id--; if (id < 0) id += numPlaces; return id; } private int right(int id) { id++; if (id >= numPlaces) id -= numPlaces; return id; } private void react_0(Philosopher.IsHungry msg) { states[msg.id] = State.HUNGRY; tryEat(msg.id); } public void deliver(Philosopher.IsHungry msg) { bufferMessage(new org.taj.ajava.runtime.ActorMessage(msg, 0)); } protected void react(Philosopher.IsHungry msg) { react_0(msg); } private void react_1(MoveForks frks) { forks[frks.id] = frks.lhf; forks[right(frks.id)] = frks.rhf; states[frks.id] = State.THINKING; tryEat(left(frks.id)); tryEat(right(frks.id)); } public void deliver(MoveForks frks) { bufferMessage(new org.taj.ajava.runtime.ActorMessage(frks, 1)); } protected void react(MoveForks frks) { react_1(frks); } private void tryEat(int id) { if (states[id] == State.HUNGRY && states[left(id)] != State.EATING && states[right(id)] != State.EATING) { states[id] = State.EATING; diners[id].deliver(new MoveForks(id, forks[id], forks[right(id)])); } } protected void processMessage(org.taj.ajava.runtime.ActorMessage msg) { switch (msg.reactorId) { case 0: { react_0(((Philosopher.IsHungry)msg.payload)); return; } case 1: { react_1(((MoveForks)msg.payload)); return; } default: { super.processMessage(msg); return; } } } }