1 4 package gnu.mapping; 5 6 8 9 public class ThreadLocation extends Location implements Named 10 { 11 final Symbol name; 12 final Object property; 13 static int counter; 14 boolean unlink; 15 private static synchronized int nextCounter() { return ++counter; } 16 17 20 public static final String ANONYMOUS = new String ("(dynamic)"); 21 22 Location global; 23 24 25 ThreadLocal thLocal = new ThreadLocal (); 26 27 29 30 31 public ThreadLocation () 32 { 33 this("param#"+nextCounter()); 34 } 35 36 38 public ThreadLocation (String name) 39 { 40 this.name = Symbol.makeUninterned(name); 41 this.property = ANONYMOUS; 42 unlink = true; 43 global = new SharedLocation(this.name, null, 0); 44 } 45 46 private ThreadLocation (Symbol name) 47 { 48 this.name = name; 49 String str = name == null ? null : name.toString(); 50 this.property = ANONYMOUS; 51 unlink = true; 52 global = new SharedLocation(Symbol.makeUninterned(str), null, 0); 53 } 54 55 public ThreadLocation (Symbol name, Object property, Location global) 56 { 57 this.name = name; 58 this.property = property; 59 this.global = global; 60 } 61 62 66 public static ThreadLocation makePrivate (String name) 67 { 68 return new ThreadLocation(name); 69 } 70 71 public static ThreadLocation makePrivate (Symbol name) 72 { 73 return new ThreadLocation(name); 74 } 75 76 77 public void setGlobal (Object value) 78 { 79 synchronized (this) 80 { 81 if (global == null) 82 global = new SharedLocation(this.name, null, 0); 83 global.set(value); 84 } 85 } 86 87 88 public Location getLocation () 89 { 90 Object entry; 91 92 entry = thLocal.get(); 93 94 96 if (entry == null) 97 { 98 Environment env = Environment.getCurrent(); 99 NamedLocation loc = env.getLocation(name, property, true); 100 if (global != null) 101 { 102 synchronized (loc) 103 { 104 if (loc.base == null && loc.value == Location.UNBOUND) 105 loc.setBase(global); 106 } 107 } 108 109 if (unlink) 110 { 111 LocationRef lref = new LocationRef(); 112 lref.env = env; 113 lref.loc = loc; 114 entry = lref; 115 } 116 else 117 entry = loc; 118 119 thLocal.set(entry); 120 121 123 } 124 if (entry instanceof LocationRef) 125 return ((LocationRef) entry).loc; 126 else 127 return (Location) entry; 128 } 129 130 public Object get (Object defaultValue) 131 { 132 return getLocation().get(defaultValue); 133 } 134 135 public void set (Object value) 136 { 137 getLocation().set(value); 138 } 139 140 public Object setWithSave (Object newValue, CallContext ctx) 141 { 142 return getLocation().setWithSave(newValue, ctx); 143 } 144 145 public void setRestore (Object oldValue, CallContext ctx) 146 { 147 getLocation().setRestore(oldValue, ctx); 148 } 149 150 public Symbol getKeySymbol () { return name; } 151 public Object getKeyProperty () { return property; } 152 public String getName () { return name == null ? null : name.toString(); } 153 public Object getSymbol () { 155 if (name != null && property == ANONYMOUS 160 && (((SharedLocation) global).getKeySymbol() == name)) 161 return name.toString(); 162 return name; 163 } 164 public void setName (String name) 165 { throw new RuntimeException ("setName not allowed"); } 166 167 static SimpleEnvironment env; 168 169 171 public synchronized static ThreadLocation 172 getInstance(Symbol name, Object property) 173 { 174 if (env == null) 175 env = new SimpleEnvironment("[thread-locations]"); 176 IndirectableLocation loc 177 = (IndirectableLocation) env.getLocation(name, property); 178 if (loc.base != null) 179 return (ThreadLocation) loc.base; 180 ThreadLocation tloc = new ThreadLocation(name, property, null); 181 loc.base = tloc; 182 return tloc; 183 } 184 } 185 186 class LocationRef 187 { 188 Environment env; 189 Location loc; 190 191 public void finalize () 192 { 193 Symbol symbol = loc.getKeySymbol(); 194 Object property = loc.getKeyProperty(); 195 int hash = symbol.hashCode() ^ System.identityHashCode(property); 196 env.unlink(symbol, property, hash); 197 } 198 } 199 | Popular Tags |