diff options
author | Rich Hickey <richhickey@gmail.com> | 2007-08-18 18:05:23 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2007-08-18 18:05:23 +0000 |
commit | 8b21472e502732159b4d2e3fa20b25089cfd9c79 (patch) | |
tree | 3d8a7f74a52f1b04242d445f1d18117d46bedf2e | |
parent | e47953186a17469875a94a00f5a98de5d1f926f3 (diff) |
interim checkin revising DynamicVar
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 14 | ||||
-rw-r--r-- | src/jvm/clojure/lang/DynamicVar.java | 209 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 6 |
3 files changed, 200 insertions, 29 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 8f900a12..56c5579d 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -45,27 +45,27 @@ static public DynamicVar _CRT_MODULE = RT.CURRENT_MODULE; static NilExpr NIL_EXPR = new NilExpr(); //short-name-string->full-name-string -static public DynamicVar IMPORTS = new DynamicVar(); +static public DynamicVar IMPORTS = DynamicVar.create(); //keyword->keywordexpr -static public DynamicVar KEYWORDS = new DynamicVar(); +static public DynamicVar KEYWORDS = DynamicVar.create(); //var->var -static public DynamicVar VARS = new DynamicVar(); +static public DynamicVar VARS = DynamicVar.create(); //symbol->localbinding -static public DynamicVar LOCAL_ENV = new DynamicVar(); +static public DynamicVar LOCAL_ENV = DynamicVar.create(); //FnFrame -static public DynamicVar METHOD = new DynamicVar(); +static public DynamicVar METHOD = DynamicVar.create(); //module->module -static public DynamicVar USES = new DynamicVar(); +static public DynamicVar USES = DynamicVar.create(); //ISeq FnExprs -static public DynamicVar FNS = new DynamicVar(); +static public DynamicVar FNS = DynamicVar.create(); static public IPersistentMap CHAR_MAP = new PersistentArrayMap(new Object[]{'-', "_DASH_", diff --git a/src/jvm/clojure/lang/DynamicVar.java b/src/jvm/clojure/lang/DynamicVar.java index 2623fc18..29be9b81 100644 --- a/src/jvm/clojure/lang/DynamicVar.java +++ b/src/jvm/clojure/lang/DynamicVar.java @@ -13,12 +13,19 @@ package clojure.lang; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; -public class DynamicVar{ -final InheritableThreadLocal<Binding> dvals; +public class DynamicVar implements IFn{ +volatile InheritableThreadLocal<Binding> dvals; Object root; +final AtomicInteger count; +final Symbol sym; + static ConcurrentHashMap<Symbol, DynamicVar> table = new ConcurrentHashMap<Symbol, DynamicVar>(); +public static DynamicVar intern(Symbol sym, Object root){ + return intern(sym, root, true); +} public static DynamicVar intern(Symbol sym, Object root, boolean replaceRoot){ DynamicVar dvout = table.get(sym); @@ -26,7 +33,7 @@ public static DynamicVar intern(Symbol sym, Object root, boolean replaceRoot){ if(!present) { - DynamicVar dvin = new DynamicVar(root); + DynamicVar dvin = new DynamicVar(sym, root); dvout = table.putIfAbsent(sym, dvin); present = dvout != dvin; //might have snuck in } @@ -46,65 +53,227 @@ public static DynamicVar intern(Symbol sym){ if(dvout != null) return dvout; - return table.putIfAbsent(sym, new DynamicVar()); + return table.putIfAbsent(sym, new DynamicVar(sym)); +} + +public static void unintern(Symbol sym){ + table.remove(sym); } public static DynamicVar find(Symbol sym){ return table.get(sym); } -public DynamicVar(){ - this.dvals = new InheritableThreadLocal<Binding>(); - this.root = dvals; //use dvals as magic not-bound value +public static DynamicVar create(){ + return new DynamicVar(null); +} + +public static DynamicVar create(Object root){ + return new DynamicVar(null, root); +} + +private DynamicVar(Symbol sym){ + this.dvals = null; + this.sym = sym; + this.count = new AtomicInteger(); + this.root = count; //use count as magic not-bound value } -public DynamicVar(Object root){ - this(); +private DynamicVar(Symbol sym, Object root){ + this(sym); this.root = root; } -boolean isBound(){ - return root != dvals || dvals.get() != null; +public boolean isBound(){ + return root != count || dvals.get() != null; } -public Object get(){ +final public Object get(){ Binding b = getThreadBinding(); if(b != null) return b.val; - if(root != dvals) + if(root != count) return root; - throw new IllegalStateException("Var is unbound."); + throw new IllegalStateException(String.format("Var %s is unbound.", sym)); } public Object set(Object val){ Binding b = getThreadBinding(); if(b != null) return (b.val = val); - throw new IllegalStateException("Var is unbound."); + //can't establish root binding with set, but can change it + if(root != count) + return root = val; + throw new IllegalStateException(String.format("Var %s has no binding in this thread.", sym)); } public Object getRoot(){ return root; } -synchronized public DynamicVar setRoot(Object root){ +public DynamicVar setRoot(Object root){ this.root = root; return this; } public void pushThreadBinding(Object val){ + if(dvals == null) + { + synchronized(this) + { + if(dvals == null) + dvals = new InheritableThreadLocal<Binding>(); + } + } dvals.set(new Binding(val, dvals.get())); + count.incrementAndGet(); } public void popThreadBinding(){ - Binding b = dvals.get(); - if(b == null) - throw new IllegalStateException("Can't pop unbound ref"); + Binding b; + if(dvals == null || (b = dvals.get()) == null) + throw new IllegalStateException(String.format("Var %s has no binding in this thread.", sym)); dvals.set(b.rest); + count.decrementAndGet(); } final Binding getThreadBinding(){ - return dvals.get(); + if(dvals != null && count.get() > 0) + return dvals.get(); + return null; +} + +final public IFn fn(){ + return (IFn) get(); +} + +public Object call() throws Exception{ + return invoke(); +} + +public Object invoke() throws Exception{ + return fn().invoke(); +} + +public Object invoke(Object arg1) throws Exception{ + return fn().invoke(arg1); +} + +public Object invoke(Object arg1, Object arg2) throws Exception{ + return fn().invoke(arg1, arg2); +} + +public Object invoke(Object arg1, Object arg2, Object arg3) throws Exception{ + 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); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) + throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8) throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9) throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10) throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11) throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12) throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13) + throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14) + throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15) throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16) throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, + arg16); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17) throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, + arg16, arg17); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17, Object arg18) throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, + arg16, arg17, arg18); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17, Object arg18, Object arg19) throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, + arg16, arg17, arg18, arg19); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20) + throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, + arg16, arg17, arg18, arg19, arg20); +} + +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20, + Object... args) + throws Exception{ + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, + arg16, arg17, arg18, arg19, arg20, args); +} + +public Object applyTo(ISeq arglist) throws Exception{ + return AFn.applyToHelper(this, arglist); } } diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index 44df9e57..8a65dfdc 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -19,10 +19,12 @@ import java.io.*; public class RT{ static public Symbol T = Symbol.create(null, "t"); -final static public DynamicVar OUT = new DynamicVar(new OutputStreamWriter(System.out)); +final static public DynamicVar OUT = + DynamicVar.intern(Symbol.create("clojure", "out"), new OutputStreamWriter(System.out)); final static Keyword TAG_KEY = new Keyword("clojure", "tag"); -final static public DynamicVar CURRENT_MODULE = new DynamicVar(Module.findOrCreateModule("clojure/user")); +final static public DynamicVar CURRENT_MODULE = DynamicVar.intern(Symbol.create("clojure", "current-module"), + Module.findOrCreateModule("clojure/user")); static public final Object[] EMPTY_ARRAY = new Object[]{}; static public final Character[] chars; |