KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > mapping > ThreadLocation


1 // Copyright (c) 2005 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.mapping;
5
6 /** A Location that forwards to a thread-specific Location.
7  */

8
9 public class ThreadLocation extends Location implements Named
10 {
11   final Symbol name;
12   final Object JavaDoc property;
13   static int counter;
14   boolean unlink;
15   private static synchronized int nextCounter() { return ++counter; }
16
17   /** Magic property value used for the "anonymous" ThreadLocations.
18    * These are thread-specific dynamic "parameters" (in the SRFI-39 sense)
19    * that are not tied to a specfic name. */

20   public static final String JavaDoc ANONYMOUS = new String JavaDoc("(dynamic)");
21
22   Location global;
23
24   /* #ifdef JAVA2 */
25   ThreadLocal JavaDoc thLocal = new ThreadLocal JavaDoc();
26   /* #else */
27   // java.util.Hashtable threadMap = new java.util.Hashtable(50);
28
/* #endif */
29
30   /** A new anonymous fluid location. */
31   public ThreadLocation ()
32   {
33     this("param#"+nextCounter());
34   }
35
36   /** A new anonymous fluid location but used a given name for printing.
37    * However, the binding is not bound to the name as a visible binding. */

38   public ThreadLocation (String JavaDoc 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 JavaDoc 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 JavaDoc property, Location global)
56   {
57     this.name = name;
58     this.property = property;
59     this.global = global;
60   }
61
62   /** Create a fresh ThreadLocation, independent of other ThreaDLocations.
63    * Creates new unique EnvironmentKey, using a unique property key.
64    * @param name used for printing, but not identification.
65    */

66   public static ThreadLocation makePrivate (String JavaDoc 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   /** Set the default/global value. */
77   public void setGlobal (Object JavaDoc 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   /** Get the thread-specific Location for this Location. */
88   public Location getLocation ()
89   {
90     Object JavaDoc entry;
91     /* #ifdef JAVA2 */
92     entry = thLocal.get();
93     /* #else */
94     // entry = threadMap.get(Thread.currentThread());
95
/* #endif */
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     /* #ifdef JAVA2 */
119     thLocal.set(entry);
120     /* #else */
121     // threadMap.put(Thread.currentThread(), entry);
122
/* #endif */
123       }
124     if (entry instanceof LocationRef)
125       return ((LocationRef) entry).loc;
126     else
127       return (Location) entry;
128   }
129
130   public Object JavaDoc get (Object JavaDoc defaultValue)
131   {
132     return getLocation().get(defaultValue);
133   }
134
135   public void set (Object JavaDoc value)
136   {
137     getLocation().set(value);
138   }
139
140   public Object JavaDoc setWithSave (Object JavaDoc newValue, CallContext ctx)
141   {
142     return getLocation().setWithSave(newValue, ctx);
143   }
144
145   public void setRestore (Object JavaDoc oldValue, CallContext ctx)
146   {
147     getLocation().setRestore(oldValue, ctx);
148   }
149
150   public Symbol getKeySymbol () { return name; }
151   public Object JavaDoc getKeyProperty () { return property; }
152   public String JavaDoc getName () { return name == null ? null : name.toString(); }
153   public Object JavaDoc getSymbol () // Implements Named
154
{
155     // If this was allocated using makePrivate(String) it is better
156
// to return the original String, rather than a generated Symbol.
157
// One motivation is when a module is imported with a specified namespace
158
// URI (only in XQuery at this point); we want to use the latter namespace.
159
if (name != null && property == ANONYMOUS
160         && (((SharedLocation) global).getKeySymbol() == name))
161       return name.toString();
162     return name;
163   }
164   public void setName (String JavaDoc name)
165   { throw new RuntimeException JavaDoc("setName not allowed"); }
166
167   static SimpleEnvironment env;
168
169   /** For a given (Symbol. property)-pair, find or create
170    * a matching ThreadLocation. */

171   public synchronized static ThreadLocation
172   getInstance(Symbol name, Object JavaDoc 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 JavaDoc property = loc.getKeyProperty();
195     int hash = symbol.hashCode() ^ System.identityHashCode(property);
196     env.unlink(symbol, property, hash);
197   }
198 }
199
Popular Tags