diff options
author | Rich Hickey <richhickey@gmail.com> | 2006-05-31 12:55:52 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2006-05-31 12:55:52 +0000 |
commit | 47bbbed7f23af23aa41e727c0909cdad09dbf4d6 (patch) | |
tree | 8653785602739179012aeecb7af4a14021740743 /src | |
parent | 8b74fbd52683934c6dde25412c4d3ec86384da87 (diff) |
refactoring
Diffstat (limited to 'src')
-rw-r--r-- | src/org/clojure/runtime/TRef.java | 19 | ||||
-rw-r--r-- | src/org/clojure/runtime/TVal.java | 3 | ||||
-rw-r--r-- | src/org/clojure/runtime/Transaction.java | 98 |
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))); -} + } } |