1 |
/* java.lang.ThreadLocal |
/* ThreadLocal -- a variable with a unique value per thread |
2 |
Copyright (C) 2000 Free Software Foundation, Inc. |
Copyright (C) 2000, 2002 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
7 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
8 |
the Free Software Foundation; either version 2, or (at your option) |
the Free Software Foundation; either version 2, or (at your option) |
9 |
any later version. |
any later version. |
10 |
|
|
11 |
GNU Classpath is distributed in the hope that it will be useful, but |
GNU Classpath is distributed in the hope that it will be useful, but |
12 |
WITHOUT ANY WARRANTY; without even the implied warranty of |
WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
46 |
* (through the <code>get()</code> and <code>set()</code> methods) |
* (through the <code>get()</code> and <code>set()</code> methods) |
47 |
* only affects the state of the object as seen by the currently |
* only affects the state of the object as seen by the currently |
48 |
* executing Thread. |
* executing Thread. |
49 |
* <p> |
* |
50 |
* The first time a ThreadLocal object is accessed on a particular |
* <p>The first time a ThreadLocal object is accessed on a particular |
51 |
* Thread (and no state is associated with that Thread yet) |
* Thread, the state for that Thread's copy of the local variable is set by |
52 |
* the state for that Thread is set by executing the method |
* executing the method <code>initialValue()</code>. |
53 |
* <code>initialValue()</code>. |
* |
54 |
* <p> |
* <p>An example how you can use this: |
|
* An example how you can use this: |
|
55 |
* <pre> |
* <pre> |
56 |
* class Connection { |
* class Connection |
57 |
* private static ThreadLocal owner = new ThreadLocal() { |
* { |
58 |
* public Object initialValue() { |
* private static ThreadLocal owner = new ThreadLocal() |
59 |
* return("nobody"); |
* { |
60 |
* } |
* public Object initialValue() |
61 |
|
* { |
62 |
|
* return("nobody"); |
63 |
|
* } |
64 |
* }; |
* }; |
65 |
* ... |
* ... |
66 |
* } |
* } |
67 |
* </pre> |
* </pre></br> |
68 |
|
* |
69 |
* Now all instances of connection can see who the owner of the currently |
* Now all instances of connection can see who the owner of the currently |
70 |
* executing Thread is by calling <code>owner.get()</code>. By default any |
* executing Thread is by calling <code>owner.get()</code>. By default any |
71 |
* Thread would be associated with 'nobody'. But the Connection object could |
* Thread would be associated with 'nobody'. But the Connection object could |
72 |
* offer a method that changes the owner associated with the Thread on |
* offer a method that changes the owner associated with the Thread on |
73 |
* which the method was called by calling <code>owner.put("somebody")</code>. |
* which the method was called by calling <code>owner.put("somebody")</code>. |
74 |
* (Such an owner changing method should then be guarded by security checks.) |
* (Such an owner changing method should then be guarded by security checks.) |
75 |
* <p> |
* |
76 |
* When a Thread is garbage collected all references to values of |
* <p>When a Thread is garbage collected all references to values of |
77 |
* the ThreadLocal objects associated with that Thread are removed. |
* the ThreadLocal objects associated with that Thread are removed. |
78 |
* |
* |
79 |
|
* @author Mark Wielaard <mark@klomp.org> |
80 |
|
* @author Eric Blake <ebb9@email.byu.edu> |
81 |
* @since 1.2 |
* @since 1.2 |
82 |
* @author Mark Wielaard (mark@klomp.org) |
* @status updated to 1.4 |
83 |
*/ |
*/ |
84 |
public class ThreadLocal { |
public class ThreadLocal |
85 |
|
{ |
86 |
/** |
/** |
87 |
* Trivial container to wrap the stored values. |
* Placeholder to distinguish between uninitialized and null set by the |
88 |
* Needed to see if the value is null or not yet set. |
* user. Do not expose this to the public. Package visible for use by |
89 |
* If it is not yet set we must call intialValue() once. |
* InheritableThreadLocal |
90 |
* Package local so InheritableThreadLocal can see it. |
*/ |
91 |
*/ |
static final Object NULL = new Object(); |
92 |
final static class Value { |
|
93 |
final Object value; |
/** |
94 |
|
* The stored value. Package visible for use by InheritableThreadLocal. */ |
95 |
Value(Object value) { |
Object value; |
96 |
this.value = value; |
|
97 |
} |
/** |
98 |
|
* Maps Threads to values. Uses a WeakHashMap so if a Thread is garbage |
99 |
Object getValue() { |
* collected the reference to the Value will disappear. A null value means |
100 |
return value; |
* uninitialized, while NULL means a user-specified null. Only the |
101 |
} |
* <code>set(Thread, Object)</code> and <code>get(Thread)</code> methods |
102 |
} |
* access it. Package visible for use by InheritableThreadLocal. |
103 |
|
*/ |
104 |
/** |
final Map valueMap = new WeakHashMap(); |
105 |
* Maps Threads to Values. Uses a WeakHashMap so if a Thread is garbage |
|
106 |
* collected the reference to the Value will disappear. Only the |
/** |
107 |
* <code>set(Thread, Value)</code> and <code>get(Thread)</code> methods |
* Creates a ThreadLocal object without associating any value to it yet. |
108 |
* access it. Since this can happen from multiple Threads simultaniously |
*/ |
109 |
* those methods are synchronized. |
public ThreadLocal() |
110 |
*/ |
{ |
111 |
private final Map valueMap = new WeakHashMap(); |
} |
112 |
|
|
113 |
/** |
/** |
114 |
* Creates a ThreadLocal object without associating any value to it |
* Called once per thread on the first invocation of get(), if set() was |
115 |
* yet. |
* not already called. The default implementation returns <code>null</code>. |
116 |
*/ |
* Often, this method is overridden to create the appropriate initial object |
117 |
public ThreadLocal() { |
* for the current thread's view of the ThreadLocal. |
118 |
} |
* |
119 |
|
* @return the initial value of the variable in this thread |
120 |
/** |
*/ |
121 |
* Gets the value associated with the ThreadLocal object for the |
protected Object initialValue() |
122 |
* currently executing Thread. If there is no value is associated |
{ |
123 |
* with this Thread yet then the valued returned by the |
return null; |
124 |
* <code>initialValue()</code> method is assosiated with this Thread |
} |
125 |
* and returned. |
|
126 |
*/ |
/** |
127 |
public Object get() { |
* Gets the value associated with the ThreadLocal object for the currently |
128 |
Thread currentThread = Thread.currentThread(); |
* executing Thread. If this is the first time the current thread has called |
129 |
Value v = get(currentThread); |
* get(), and it has not already called set(), the value is obtained by |
130 |
if (v == null) { |
* <code>initialValue()</code>. |
131 |
v = new Value(initialValue()); |
* |
132 |
set(currentThread, v); |
* @return the value of the variable in this thread |
133 |
} |
*/ |
134 |
return v.getValue(); |
public Object get() |
135 |
} |
{ |
136 |
|
Thread currentThread = Thread.currentThread(); |
137 |
/** |
// Note that we don't have to synchronize, as only this thread will |
138 |
* Gets the Value of this ThreadLocal for a particular Thread. |
// ever modify the returned value. |
139 |
* It is synchronized so the <code>set(Thread, Value)</code> method cannot |
Object value = valueMap.get(currentThread); |
140 |
* simultaniously modify the </code>valueMap</code> from another thread. |
if (value == null) |
141 |
* Package local so InheritableThreadLocal can access it when a new child |
{ |
142 |
* Thread inherits values from its parent Thread. |
value = initialValue(); |
143 |
*/ |
valueMap.put(currentThread, value == null ? NULL : value); |
144 |
synchronized final Value get(Thread thread) { |
} |
145 |
return (Value)valueMap.get(thread); |
return value == NULL ? null : value; |
146 |
} |
} |
147 |
|
|
148 |
/** |
/** |
149 |
* Sets the value associated with the ThreadLocal object for the |
* Sets the value associated with the ThreadLocal object for the currently |
150 |
* currently executing Thread. This overrides any existing value |
* executing Thread. This overrides any existing value associated with the |
151 |
* associated with the current Thread and does not call the |
* current Thread and prevents <code>initialValue()</code> from being |
152 |
* <code>initialValue()</code> method, even if this is the first |
* called if this is the first access to this ThreadLocal in this Thread. |
153 |
* time this Thread accesses this ThreadLocal. |
* |
154 |
*/ |
* @param value the value to set this thread's view of the variable to |
155 |
public void set(Object value) { |
*/ |
156 |
Thread currentThread = Thread.currentThread(); |
public void set(Object value) |
157 |
Value v = new Value(value); |
{ |
158 |
set(currentThread, v); |
// Note that we don't have to synchronize, as only this thread will |
159 |
} |
// ever modify the returned value. |
160 |
|
valueMap.put(Thread.currentThread(), value == null ? NULL : value); |
161 |
/** |
} |
|
* Sets the Value for this ThreadLocal for a particular Thread. |
|
|
* It is synchronized so the <code>get(Thread)</code> method cannot |
|
|
* simultaniously read the </code>valueMap</code> from another thread. |
|
|
* Package local so InheritableThreadLocal can access it when a new child |
|
|
* Thread inherits values from its parent Thread. |
|
|
*/ |
|
|
synchronized final void set(Thread thread, Value value) { |
|
|
valueMap.put(thread, value); |
|
|
} |
|
|
|
|
|
/** |
|
|
* Called when <code>get()</code> is called and no state is associated |
|
|
* with the currently executing Thread yet. |
|
|
* <p> |
|
|
* The default implementation returns <code>null</code>. |
|
|
*/ |
|
|
protected Object initialValue() { |
|
|
return null; |
|
|
} |
|
162 |
} |
} |