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.ajava

home Home   up Up   ( Download )


public aclass Table { 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; } // when a philosopher becomes hungry, updates its // state, and tries to eat public react (Philosopher.IsHungry msg) { // update state states[msg.id] = State.HUNGRY; // try and eat tryEat(msg.id); } // when receives some forks from a philosopher // records the fact it is thinking, and tries // serve its neighbours public react (MoveForks frks) { // return forks forks[frks.id] <-- frks.lhf; forks[right(frks.id)] <-- frks.rhf; states[frks.id] = State.THINKING; // try left and right tryEat(left(frks.id)); tryEat(right(frks.id)); } // if the philosopher is hungry, and neither // neighbour is eating, then pass it its forks. private void tryEat(int id) { // if hungry, and left not eat, and right not eating if (states[id] == State.HUNGRY && states[left(id)] != State.EATING && states[right(id)] != State.EATING) { // move forks to the philosopher states[id] = State.EATING; diners[id] <-- new MoveForks(id, forks[id], forks[right(id)]); // remember: forks[id] and forks[right] are destructive reads // as are linear objects } } }