summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2006-07-05 19:37:11 +0000
committerRich Hickey <richhickey@gmail.com>2006-07-05 19:37:11 +0000
commit8a628fcd1b1e015ef61272df128cf4cbfa323259 (patch)
tree532d7bff25d7fde94be72c4c985a38a29e6d09b5
parente5dcae7b0a24af84476b1192563fa149ad6a4a96 (diff)
added tcount, removed fn member, now fn vals are dynamically bindable
-rw-r--r--src/cli/runtime/Var.cs15
-rw-r--r--src/jvm/clojure/lang/Var.java89
2 files changed, 76 insertions, 28 deletions
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<IPersistentMap> 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<n;i++)
+ result = test.invoke(result);
+ long estimatedTime = System.nanoTime() - startTime;
+ System.out.println("val:" + result + ", time: " + estimatedTime/1000000);
+
+ rand = new Random(42);
+ startTime = System.nanoTime();
+
+ for(int i=0;i<n;i++)
+ result = ((IFn)test.getValue()).invoke(result);
+ estimatedTime = System.nanoTime() - startTime;
+ System.out.println("val:" + result + ", time: " + estimatedTime/1000000);
+
+ }
+
+ catch (Exception e)
+ {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ }
+
+}
}