summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2007-12-02 03:57:35 +0000
committerRich Hickey <richhickey@gmail.com>2007-12-02 03:57:35 +0000
commitb2bd83819314795cf43defcd361d77271467ca8d (patch)
tree79b1b112e7514cdc1c1a30368e16ba32e0203907 /src
parentce3b83c95f6758dbb40c031eb131a09e6650173a (diff)
interim checkin
Diffstat (limited to 'src')
-rw-r--r--src/jvm/clojure/lang/Actor.java43
1 files changed, 42 insertions, 1 deletions
diff --git a/src/jvm/clojure/lang/Actor.java b/src/jvm/clojure/lang/Actor.java
index 6d17b2ce..62c984c7 100644
--- a/src/jvm/clojure/lang/Actor.java
+++ b/src/jvm/clojure/lang/Actor.java
@@ -22,12 +22,14 @@ public class Actor implements IRef{
volatile Object state;
final Queue q = new LinkedList();
boolean busy = false;
+boolean commuting = false;
volatile ISeq errors = null;
//todo - make tuneable
final static Executor executor = Executors.newFixedThreadPool(2 + Runtime.getRuntime().availableProcessors());
//final static Executor executor = Executors.newCachedThreadPool();
final static ThreadLocal<PersistentVector> nested = new ThreadLocal<PersistentVector>();
+final static ThreadLocal inChange = new ThreadLocal();
static class Action implements Runnable{
final Actor actor;
@@ -46,7 +48,7 @@ static class Action implements Runnable{
boolean hadError = false;
try
{
- actor.setState(fn.applyTo(RT.cons(actor.state, args)));
+ actor.commute(fn, args);
}
catch(Exception e)
{
@@ -108,6 +110,45 @@ public void clearErrors(){
errors = null;
}
+synchronized void commute(IFn fn, ISeq args) throws Exception{
+ try
+ {
+ commuting = true;
+ setState(fn.applyTo(RT.cons(state, args)));
+ }
+ finally
+ {
+ commuting = false;
+ }
+}
+
+public Object change(IFn fn, ISeq args) throws Exception{
+ if(errors != null)
+ {
+ throw new Exception("Actor has errors", (Exception) RT.first(errors));
+ }
+ //Action action = new Action(this, fn, args);
+ if(commuting)
+ throw new Exception("Recursive change");
+ LockingTransaction trans = LockingTransaction.getRunning();
+ if(trans != null)
+ throw new Exception("Cannot change an Actor in a transaction");
+ if(inChange.get() != null)
+ throw new Exception("Cannot nest changes, use send");
+
+ try
+ {
+ inChange.set(this);
+ commute(fn, args);
+ }
+ finally
+ {
+ inChange.set(null);
+ }
+
+ return this;
+}
+
public Object send(IFn fn, ISeq args) throws Exception{
if(errors != null)
{