rlm@10: /** rlm@10: * Copyright (c) Rich Hickey. All rights reserved. rlm@10: * The use and distribution terms for this software are covered by the rlm@10: * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) rlm@10: * which can be found in the file epl-v10.html at the root of this distribution. rlm@10: * By using this software in any fashion, you are agreeing to be bound by rlm@10: * the terms of this license. rlm@10: * You must not remove this notice, or any other, from this software. rlm@10: **/ rlm@10: rlm@10: /* rich Jul 25, 2007 */ rlm@10: rlm@10: package clojure.lang; rlm@10: rlm@10: import java.util.concurrent.atomic.AtomicInteger; rlm@10: import java.util.concurrent.atomic.AtomicLong; rlm@10: import java.util.concurrent.locks.ReentrantReadWriteLock; rlm@10: rlm@10: public class Ref extends ARef implements IFn, Comparable, IRef{ rlm@10: public int compareTo(Ref ref) { rlm@10: if(this.id == ref.id) rlm@10: return 0; rlm@10: else if(this.id < ref.id) rlm@10: return -1; rlm@10: else rlm@10: return 1; rlm@10: } rlm@10: rlm@10: public int getMinHistory(){ rlm@10: return minHistory; rlm@10: } rlm@10: rlm@10: public Ref setMinHistory(int minHistory){ rlm@10: this.minHistory = minHistory; rlm@10: return this; rlm@10: } rlm@10: rlm@10: public int getMaxHistory(){ rlm@10: return maxHistory; rlm@10: } rlm@10: rlm@10: public Ref setMaxHistory(int maxHistory){ rlm@10: this.maxHistory = maxHistory; rlm@10: return this; rlm@10: } rlm@10: rlm@10: public static class TVal{ rlm@10: Object val; rlm@10: long point; rlm@10: long msecs; rlm@10: TVal prior; rlm@10: TVal next; rlm@10: rlm@10: TVal(Object val, long point, long msecs, TVal prior){ rlm@10: this.val = val; rlm@10: this.point = point; rlm@10: this.msecs = msecs; rlm@10: this.prior = prior; rlm@10: this.next = prior.next; rlm@10: this.prior.next = this; rlm@10: this.next.prior = this; rlm@10: } rlm@10: rlm@10: TVal(Object val, long point, long msecs){ rlm@10: this.val = val; rlm@10: this.point = point; rlm@10: this.msecs = msecs; rlm@10: this.next = this; rlm@10: this.prior = this; rlm@10: } rlm@10: rlm@10: } rlm@10: rlm@10: TVal tvals; rlm@10: final AtomicInteger faults; rlm@10: final ReentrantReadWriteLock lock; rlm@10: LockingTransaction.Info tinfo; rlm@10: //IFn validator; rlm@10: final long id; rlm@10: rlm@10: volatile int minHistory = 0; rlm@10: volatile int maxHistory = 10; rlm@10: rlm@10: static final AtomicLong ids = new AtomicLong(); rlm@10: rlm@10: public Ref(Object initVal) throws Exception{ rlm@10: this(initVal, null); rlm@10: } rlm@10: rlm@10: public Ref(Object initVal,IPersistentMap meta) throws Exception{ rlm@10: super(meta); rlm@10: this.id = ids.getAndIncrement(); rlm@10: this.faults = new AtomicInteger(); rlm@10: this.lock = new ReentrantReadWriteLock(); rlm@10: tvals = new TVal(initVal, 0, System.currentTimeMillis()); rlm@10: } rlm@10: rlm@10: //the latest val rlm@10: rlm@10: // ok out of transaction rlm@10: Object currentVal(){ rlm@10: try rlm@10: { rlm@10: lock.readLock().lock(); rlm@10: if(tvals != null) rlm@10: return tvals.val; rlm@10: throw new IllegalStateException(this.toString() + " is unbound."); rlm@10: } rlm@10: finally rlm@10: { rlm@10: lock.readLock().unlock(); rlm@10: } rlm@10: } rlm@10: rlm@10: //* rlm@10: rlm@10: public Object deref(){ rlm@10: LockingTransaction t = LockingTransaction.getRunning(); rlm@10: if(t == null) rlm@10: return currentVal(); rlm@10: return t.doGet(this); rlm@10: } rlm@10: rlm@10: //void validate(IFn vf, Object val){ rlm@10: // try{ rlm@10: // if(vf != null && !RT.booleanCast(vf.invoke(val))) rlm@10: // throw new IllegalStateException("Invalid ref state"); rlm@10: // } rlm@10: // catch(RuntimeException re) rlm@10: // { rlm@10: // throw re; rlm@10: // } rlm@10: // catch(Exception e) rlm@10: // { rlm@10: // throw new IllegalStateException("Invalid ref state", e); rlm@10: // } rlm@10: //} rlm@10: // rlm@10: //public void setValidator(IFn vf){ rlm@10: // try rlm@10: // { rlm@10: // lock.writeLock().lock(); rlm@10: // validate(vf,currentVal()); rlm@10: // validator = vf; rlm@10: // } rlm@10: // finally rlm@10: // { rlm@10: // lock.writeLock().unlock(); rlm@10: // } rlm@10: //} rlm@10: // rlm@10: //public IFn getValidator(){ rlm@10: // try rlm@10: // { rlm@10: // lock.readLock().lock(); rlm@10: // return validator; rlm@10: // } rlm@10: // finally rlm@10: // { rlm@10: // lock.readLock().unlock(); rlm@10: // } rlm@10: //} rlm@10: rlm@10: public Object set(Object val){ rlm@10: return LockingTransaction.getEx().doSet(this, val); rlm@10: } rlm@10: rlm@10: public Object commute(IFn fn, ISeq args) throws Exception{ rlm@10: return LockingTransaction.getEx().doCommute(this, fn, args); rlm@10: } rlm@10: rlm@10: public Object alter(IFn fn, ISeq args) throws Exception{ rlm@10: LockingTransaction t = LockingTransaction.getEx(); rlm@10: return t.doSet(this, fn.applyTo(RT.cons(t.doGet(this), args))); rlm@10: } rlm@10: rlm@10: public void touch(){ rlm@10: LockingTransaction.getEx().doEnsure(this); rlm@10: } rlm@10: rlm@10: //*/ rlm@10: boolean isBound(){ rlm@10: try rlm@10: { rlm@10: lock.readLock().lock(); rlm@10: return tvals != null; rlm@10: } rlm@10: finally rlm@10: { rlm@10: lock.readLock().unlock(); rlm@10: } rlm@10: } rlm@10: rlm@10: rlm@10: public void trimHistory(){ rlm@10: try rlm@10: { rlm@10: lock.writeLock().lock(); rlm@10: if(tvals != null) rlm@10: { rlm@10: tvals.next = tvals; rlm@10: tvals.prior = tvals; rlm@10: } rlm@10: } rlm@10: finally rlm@10: { rlm@10: lock.writeLock().unlock(); rlm@10: } rlm@10: } rlm@10: rlm@10: public int getHistoryCount(){ rlm@10: try rlm@10: { rlm@10: lock.writeLock().lock(); rlm@10: return histCount(); rlm@10: } rlm@10: finally rlm@10: { rlm@10: lock.writeLock().unlock(); rlm@10: } rlm@10: } rlm@10: rlm@10: int histCount(){ rlm@10: if(tvals == null) rlm@10: return 0; rlm@10: else rlm@10: { rlm@10: int count = 0; rlm@10: for(TVal tv = tvals.next;tv != tvals;tv = tv.next) rlm@10: count++; rlm@10: return count; rlm@10: } rlm@10: } rlm@10: rlm@10: final public IFn fn(){ rlm@10: return (IFn) deref(); rlm@10: } rlm@10: rlm@10: public Object call() throws Exception{ rlm@10: return invoke(); rlm@10: } rlm@10: rlm@10: public void run(){ rlm@10: try rlm@10: { rlm@10: invoke(); rlm@10: } rlm@10: catch(Exception e) rlm@10: { rlm@10: throw new RuntimeException(e); rlm@10: } rlm@10: } rlm@10: rlm@10: public Object invoke() throws Exception{ rlm@10: return fn().invoke(); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1) throws Exception{ rlm@10: return fn().invoke(arg1); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2) throws Exception{ rlm@10: return fn().invoke(arg1, arg2); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) rlm@10: throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9, Object arg10) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9, Object arg10, Object arg11) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9, Object arg10, Object arg11, Object arg12) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13) rlm@10: throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14) rlm@10: throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, rlm@10: Object arg15) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, rlm@10: Object arg15, Object arg16) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, rlm@10: arg16); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, rlm@10: Object arg15, Object arg16, Object arg17) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, rlm@10: arg16, arg17); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, rlm@10: Object arg15, Object arg16, Object arg17, Object arg18) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, rlm@10: arg16, arg17, arg18); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, rlm@10: Object arg15, Object arg16, Object arg17, Object arg18, Object arg19) throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, rlm@10: arg16, arg17, arg18, arg19); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, rlm@10: Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20) rlm@10: throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, rlm@10: arg16, arg17, arg18, arg19, arg20); rlm@10: } rlm@10: rlm@10: public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, rlm@10: Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, rlm@10: Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20, rlm@10: Object... args) rlm@10: throws Exception{ rlm@10: return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, rlm@10: arg16, arg17, arg18, arg19, arg20, args); rlm@10: } rlm@10: rlm@10: public Object applyTo(ISeq arglist) throws Exception{ rlm@10: return AFn.applyToHelper(this, arglist); rlm@10: } rlm@10: rlm@10: }