summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2006-05-31 12:55:52 +0000
committerRich Hickey <richhickey@gmail.com>2006-05-31 12:55:52 +0000
commit47bbbed7f23af23aa41e727c0909cdad09dbf4d6 (patch)
tree8653785602739179012aeecb7af4a14021740743 /src
parent8b74fbd52683934c6dde25412c4d3ec86384da87 (diff)
refactoring
Diffstat (limited to 'src')
-rw-r--r--src/org/clojure/runtime/TRef.java19
-rw-r--r--src/org/clojure/runtime/TVal.java3
-rw-r--r--src/org/clojure/runtime/Transaction.java98
3 files changed, 67 insertions, 53 deletions
diff --git a/src/org/clojure/runtime/TRef.java b/src/org/clojure/runtime/TRef.java
index 36b2866e..a955cdf5 100644
--- a/src/org/clojure/runtime/TRef.java
+++ b/src/org/clojure/runtime/TRef.java
@@ -22,26 +22,9 @@ static AtomicInteger nextSeq = new AtomicInteger(1);
final int lockSeq;
Lock lock;
-public TRef(ThreadLocalData tld, Object val) throws Exception{
+public TRef() {
this.lockSeq = nextSeq.getAndIncrement();
this.lock = new ReentrantLock();
- set(tld, val);
-}
-
-public Object get(ThreadLocalData tld) throws Exception{
- return tld.getTransaction().get(this);
-}
-
-public Object set(ThreadLocalData tld, Object val) throws Exception{
- return tld.getTransaction().set(this,val);
-}
-
-public void touch(ThreadLocalData tld) throws Exception{
- tld.getTransaction().touch(this);
-}
-
-public void commutate(ThreadLocalData tld, IFn fn) throws Exception{
- tld.getTransaction().commutate(this, fn);
}
public int compareTo(Object o){
diff --git a/src/org/clojure/runtime/TVal.java b/src/org/clojure/runtime/TVal.java
index 6d95fcac..edcd330d 100644
--- a/src/org/clojure/runtime/TVal.java
+++ b/src/org/clojure/runtime/TVal.java
@@ -18,7 +18,8 @@ volatile Transaction.Info tinfo;
volatile TVal prior;
void push(Object val,Transaction.Info tinfo) throws Exception{
- this.prior = (TVal) this.clone();
+ if(tinfo != null) //not newly created
+ this.prior = (TVal) this.clone();
this.tinfo = tinfo;
this.val = val;
}
diff --git a/src/org/clojure/runtime/Transaction.java b/src/org/clojure/runtime/Transaction.java
index 27f56433..d6f4cab6 100644
--- a/src/org/clojure/runtime/Transaction.java
+++ b/src/org/clojure/runtime/Transaction.java
@@ -19,49 +19,87 @@ public class Transaction{
public static final int COMMITTED = 0;
public static final int WORKING = 1;
static final Object lock = new Object();
-static int nextSeq = 1;
+
+volatile static int nextSeq = 1;
+
+static int getNextSeq(){
+ synchronized(lock){
+ return nextSeq++;
+ }
+}
public static class Info{
int seq;
int status;
+
Info(int seq,int status){
this.seq = seq;
this.status = status;
}
}
+
Info info;
int startSeq;
IdentityHashMap<TRef,Object> sets;
IdentityHashMap<TRef,Cons> commutates;
-ArrayList<TRef> locks;
-ArrayList<TRef> locked;
static public Object runInTransaction(ThreadLocalData tld,IFn fn) throws Exception{
if(tld.transaction != null)
return fn.invoke(tld);
-
tld.transaction = new Transaction();
- return tld.transaction.run(tld, fn);
+ try{
+ return tld.transaction.run(tld, fn);
+ }
+ finally{
+ tld.transaction = null;
+ }
}
-public Object run(ThreadLocalData tld, IFn fn) throws Exception{
+static public TRef tref(ThreadLocalData tld, Object val) throws Exception{
+ Transaction trans = tld.getTransaction();
+ TRef tref = new TRef();
+ trans.set(tref, val);
+ return tref;
+}
+
+static public Object get(ThreadLocalData tld, TRef tref) throws Exception{
+ return tld.getTransaction().get(tref);
+}
+
+static public Object set(ThreadLocalData tld, TRef tref, Object val) throws Exception{
+ return tld.getTransaction().set(tref,val);
+}
+
+static public void touch(ThreadLocalData tld, TRef tref) throws Exception{
+ tld.getTransaction().touch(tref);
+}
+
+static public void commutate(ThreadLocalData tld, TRef tref, IFn fn) throws Exception{
+ tld.getTransaction().commutate(tref, fn);
+}
+
+
+Object run(ThreadLocalData tld, IFn fn) throws Exception{
boolean done = false;
Object ret = null;
+ ArrayList<TRef> locks = null;
+ ArrayList<TRef> locked = null;
loop:
while(!done){
try
{
- reset();
ret = fn.invoke(tld);
+ if(locks == null && (sets != null || commutates != null))
+ locks = new ArrayList<TRef>();
if(sets != null)
- getLocks().addAll(sets.keySet());
+ locks.addAll(sets.keySet());
if(commutates != null)
- getLocks().addAll(commutates.keySet());
+ locks.addAll(commutates.keySet());
if(locks != null)
{
if(locked == null)
@@ -77,7 +115,7 @@ public Object run(ThreadLocalData tld, IFn fn) throws Exception{
{
//try again if the thing we are trying to set has changed since we started
TVal curr = getCurrent(tref);
- if(curr.tinfo.seq > startSeq)
+ if(curr != null && curr.tinfo.seq > startSeq)
continue loop;
}
}
@@ -88,6 +126,7 @@ public Object run(ThreadLocalData tld, IFn fn) throws Exception{
for(Map.Entry<TRef, Cons> e : commutates.entrySet())
{
TRef tref = e.getKey();
+ //note this will npe if tref has never been set, as designed
Object val = getCurrent(tref).val;
for(Cons c = e.getValue();c!=null;c = c.rest)
{
@@ -119,35 +158,25 @@ public Object run(ThreadLocalData tld, IFn fn) throws Exception{
{
tref.lock.unlock();
}
+ locked.clear();
}
+ reset();
+ if(locks != null)
+ locks.clear();
+ }
}
- }
return ret;
}
-ArrayList<TRef> getLocks(){
- if(locks == null)
- locks = new ArrayList<TRef>();
- return locks;
-}
-
private void reset(){
if(sets != null)
sets.clear();
if(commutates != null)
commutates.clear();
- if(locks != null)
- locks.clear();
- if(locked != null)
- locked.clear();
+
}
-int getNextSeq(){
- synchronized(lock){
- return nextSeq++;
- }
-}
Transaction(){
synchronized(lock){
int seq = getNextSeq();
@@ -162,43 +191,44 @@ Object get(TRef tref) throws Exception{
for(TVal ver = tref;ver != null;ver = ver.prior)
{
+ //note this will npe if tref has never been set, as designed
if(ver.tinfo.status == COMMITTED && ver.tinfo.seq <= startSeq)
return ver.val;
}
throw new Exception("Version not found");
-
}
static TVal getCurrent(TRef tref) throws Exception{
for(TVal ver = tref;ver != null;ver = ver.prior)
{
- if(ver.tinfo.status == COMMITTED)
+ if(ver.tinfo != null && ver.tinfo.status == COMMITTED)
return ver;
}
- throw new Exception("Version not found");
+ //this return only if no value was ever successfully set
+ return null;
}
Object set(TRef tref, Object val) throws Exception{
if(sets == null)
sets = new IdentityHashMap<TRef,Object>();
- if(commutates.containsKey(tref))
+ if(commutates != null && commutates.containsKey(tref))
throw new Exception("Can't commutate and set a TRef in the same transaction");
sets.put(tref,val);
return val;
-}
+ }
void touch(TRef tref) throws Exception{
set(tref, get(tref));
-}
+ }
void commutate(TRef tref, IFn fn) throws Exception{
if(commutates == null)
commutates = new IdentityHashMap<TRef,Cons>();
- if(sets.containsKey(tref))
+ if(sets != null && sets.containsKey(tref))
throw new Exception("Can't commutate and set a TRef in the same transaction");
commutates.put(tref, RT.cons(fn, commutates.get(tref)));
-}
+ }
}