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

Philosopher.java

home Home   up Up   ( Download )


import java.util.Random; import org.taj.ajava.lang.*; public class Philosopher extends Actor { private int id; private Table table; private Fork lhf, rhf; private int state; public Philosopher(Table table, int id) { this.table = table; this.id = id; this.state = State.THINKING; printStatus("thinking"); randomDelay(); } private void think() { table.deliver(new MoveForks(id, lhf, rhf)); state = State.THINKING; randomDelay(); printStatus("thinking"); } public static class IsHungry { public int id; public IsHungry(int id) { this.id = id; } } private void hungry() { state = State.HUNGRY; printStatus("hungry"); table.deliver(new IsHungry(id)); } private void react_0(MoveForks frks) { this.lhf = frks.lhf; this.rhf = frks.rhf; eat(); } public void deliver(MoveForks frks) { bufferMessage(new org.taj.ajava.runtime.ActorMessage(frks, 0)); } protected void react(MoveForks frks) { react_0(frks); } private void eat() { state = State.EATING; randomDelay(); printStatus("eating with fork " + Integer.toString(lhf.getId()) + " and " + Integer.toString(rhf.getId())); } private void printStatus(String status) { Stdout.getInstance().deliver("Philosopher " + Integer.toString(id) + " is " + status + "\n"); } private static final Random RNG = new Random(); private int countdown; private void randomDelay() { countdown = RNG.nextInt(10) + 1; } private void react_1(Clock.Tick t) { countdown--; if (countdown == 0) proceed(); } public void deliver(Clock.Tick t) { bufferMessage(new org.taj.ajava.runtime.ActorMessage(t, 1)); } protected void react(Clock.Tick t) { react_1(t); } private void proceed() { if (state == State.THINKING) { hungry(); } else { if (state == State.EATING) { think(); } } } protected void processMessage(org.taj.ajava.runtime.ActorMessage msg) { switch (msg.reactorId) { case 0: { react_0(((MoveForks)msg.payload)); return; } case 1: { react_1(((Clock.Tick)msg.payload)); return; } default: { super.processMessage(msg); return; } } } }