From 8a628fcd1b1e015ef61272df128cf4cbfa323259 Mon Sep 17 00:00:00 2001 From: Rich Hickey Date: Wed, 5 Jul 2006 19:37:11 +0000 Subject: added tcount, removed fn member, now fn vals are dynamically bindable --- src/cli/runtime/Var.cs | 15 ++++---- src/jvm/clojure/lang/Var.java | 89 +++++++++++++++++++++++++++++++++---------- 2 files changed, 76 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/cli/runtime/Var.cs b/src/cli/runtime/Var.cs index 9da1ef31..5df61798 100644 --- a/src/cli/runtime/Var.cs +++ b/src/cli/runtime/Var.cs @@ -15,31 +15,30 @@ namespace clojure.lang { public class Var : AFn { -public readonly Symbol sym; public Namespace ns; public Binding binding; public IFn fn; //todo, bind to throw stub? public IFn setfn; volatile IPersistentMap threadBindings = PersistentArrayIdentityMap.EMPTY; internal Var(Symbol sym, Namespace ns) { if(sym.GetType() != typeof(Symbol)) throw new ArgumentException("Only simple symbols can be vars"); this.ns = ns; this.sym = sym; } override public String ToString() { if(ns == null) return "#:" + sym; return ns.name + ":" + sym; } public Var bind(Object val) { if(binding == null) +public readonly Symbol sym; public Namespace ns; public Binding binding; volatile IPersistentMap threadBindings = PersistentArrayIdentityMap.EMPTY; volatile int tcount = 0; internal Var(Symbol sym, Namespace ns) { if(sym.GetType() != typeof(Symbol)) throw new ArgumentException("Only simple symbols can be vars"); this.ns = ns; this.sym = sym; } override public String ToString() { if(ns == null) return "#:" + sym; return ns.name + ":" + sym; } public Var bind(Object val) { if(binding == null) binding = new Binding(val); else binding.val = val; - if (val is IFn) - this.fn = (IFn)val; - else - this.fn = null; //todo, bind to throw stub? return this; } public Object getValue() { + return this; } public Object getValue() { Binding binding = getBinding(); if(binding != null) return binding.val; throw new InvalidOperationException(this.ToString() + " is unbound."); } public Object setValue(Object val) { Binding b = getThreadBinding(); if(b != null) return b.val = val; if(binding == null) - throw new InvalidOperationException(this.ToString() + " is unbound."); if(val is IFn) this.fn = (IFn) val; else this.fn = null; //todo, bind to throw stub? return binding.val = val; } + throw new InvalidOperationException(this.ToString() + " is unbound."); return binding.val = val; } public Binding pushThreadBinding(Object val) { Binding ret = new Binding(val, getThreadBinding()); setThreadBinding(ret); + Interlocked.Increment(ref tcount); return ret; } public void popThreadBinding() { setThreadBinding(getThreadBinding().rest); + Interlocked.Decrement(ref tcount); } Binding getBinding() { Binding b = getThreadBinding(); if(b != null) return b; return binding; } Binding getThreadBinding() { - if (threadBindings.count() > 0) + if (tcount != 0) return (Binding)threadBindings.get(Thread.CurrentThread); return null; } void setThreadBinding(Binding b) { Thread thread = Thread.CurrentThread; IPersistentMap tb; @@ -52,5 +51,5 @@ Binding getThreadBinding() { else newtb = tb.put(thread, b); } while (tb != Interlocked.CompareExchange(ref threadBindings, newtb, tb)); -} override public Object invoke() /*throws Exception*/ { return fn.invoke(); } override public Object invoke( Object arg1) /*throws Exception*/ { return fn.invoke(arg1); } override public Object invoke( Object arg1, Object arg2) /*throws Exception*/ { return fn.invoke(arg1,arg2); } override public Object invoke( Object arg1, Object arg2, Object arg3) /*throws Exception*/ { return fn.invoke(arg1,arg2,arg3); } override public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4) /*throws Exception*/ { return fn.invoke(arg1,arg2,arg3,arg4); } override public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) /*throws Exception*/ { return fn.invoke(arg1,arg2,arg3,arg4,arg5); } override public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, params Object[] args) /*throws Exception*/ { return fn.invoke(arg1,arg2,arg3,arg4,arg5,args); } } +} private IFn fn(){ return (IFn)getValue(); } override public Object invoke() /*throws Exception*/ { return fn().invoke(); } override public Object invoke( Object arg1) /*throws Exception*/ { return fn().invoke(arg1); } override public Object invoke( Object arg1, Object arg2) /*throws Exception*/ { return fn().invoke(arg1,arg2); } override public Object invoke( Object arg1, Object arg2, Object arg3) /*throws Exception*/ { return fn().invoke(arg1,arg2,arg3); } override public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4) /*throws Exception*/ { return fn().invoke(arg1,arg2,arg3,arg4); } override public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) /*throws Exception*/ { return fn().invoke(arg1,arg2,arg3,arg4,arg5); } override public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, params Object[] args) /*throws Exception*/ { return fn().invoke(arg1,arg2,arg3,arg4,arg5,args); } } } diff --git a/src/jvm/clojure/lang/Var.java b/src/jvm/clojure/lang/Var.java index a04c8f2a..dfed1144 100644 --- a/src/jvm/clojure/lang/Var.java +++ b/src/jvm/clojure/lang/Var.java @@ -13,14 +13,15 @@ package clojure.lang; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.Random; public class Var extends AFn { public final Symbol sym; public Namespace namespace; public Binding binding; -public IFn fn; //todo, bind to throw stub? -public IFn setfn; +AtomicInteger tcount = new AtomicInteger(0); AtomicReference threadBindings = new AtomicReference(PersistentArrayIdentityMap.EMPTY); Var(Symbol sym, Namespace ns) { @@ -42,11 +43,6 @@ public Var bind(Object val) { else binding.val = val; - if (val instanceof IFn) - this.fn = (IFn) val; - else - this.fn = null; //todo, bind to throw stub? - return this; } @@ -64,26 +60,23 @@ public Object setValue(Object val) { if (binding == null) throw new IllegalStateException(this.toString() + " is unbound."); - if (val instanceof IFn) - this.fn = (IFn) val; - else - this.fn = null; //todo, bind to throw stub? - return binding.val = val; } public Binding pushThreadBinding(Object val) { Binding ret = new Binding(val, getThreadBinding()); setThreadBinding(ret); + tcount.incrementAndGet(); return ret; } public void popThreadBinding() { setThreadBinding(getThreadBinding().rest); + tcount.decrementAndGet(); } private Binding getThreadBinding() { - if (threadBindings.get().count() > 0) + if (tcount.get() != 0) return (Binding) threadBindings.get().get(Thread.currentThread()); return null; } @@ -109,34 +102,90 @@ private void setThreadBinding(Binding b) { } while (!threadBindings.compareAndSet(tb, newtb)); } +private IFn fn(){ + return (IFn)getValue(); +} + public Object invoke() throws Exception { - return fn.invoke(); + return fn().invoke(); } public Object invoke(Object arg1) throws Exception { - return fn.invoke(arg1); + return fn().invoke(arg1); } public Object invoke(Object arg1, Object arg2) throws Exception { - return fn.invoke(arg1, arg2); + return fn().invoke(arg1, arg2); } public Object invoke(Object arg1, Object arg2, Object arg3) throws Exception { - return fn.invoke(arg1, arg2, arg3); + return fn().invoke(arg1, arg2, arg3); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4) throws Exception { - return fn.invoke(arg1, arg2, arg3, arg4); + return fn().invoke(arg1, arg2, arg3, arg4); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) throws Exception { - return fn.invoke(arg1, arg2, arg3, arg4, arg5); + return fn().invoke(arg1, arg2, arg3, arg4, arg5); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object... args) throws Exception { - return fn.invoke(arg1, arg2, arg3, arg4, arg5, args); + return fn().invoke(arg1, arg2, arg3, arg4, arg5, args); } +static volatile Integer o = 1; + +public static void main(String[] args){ + + try + { + int n = Integer.parseInt(args[0]); + class Test extends AFn{ + int x = 0; + public Object invoke(Object arg1) throws Exception { + x += o.intValue(); + return this; + } + + public String toString() { + return Integer.toString(x); + } + + } + + Var test = Namespace.intern("test", "test"); + + test.bind(new Test()); + + Random rand; + + Object result = 0; + + rand = new Random(42); + long startTime = System.nanoTime(); + + for(int i=0;i