1 /* ThreadLocal -- a variable with a unique value per thread 2 Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 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) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 19 02111-1307 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 package java.lang; 39 40 import java.util.Collections; 41 import java.util.Map; 42 import java.util.WeakHashMap; 43 44 /** 45 * ThreadLocal objects have a different state associated with every 46 * Thread that accesses them. Every access to the ThreadLocal object 47 * (through the <code>get()</code> and <code>set()</code> methods) 48 * only affects the state of the object as seen by the currently 49 * executing Thread. 50 * 51 * <p>The first time a ThreadLocal object is accessed on a particular 52 * Thread, the state for that Thread's copy of the local variable is set by 53 * executing the method <code>initialValue()</code>. 54 * 55 * <p>An example how you can use this: 56 * <pre> 57 * class Connection 58 * { 59 * private static ThreadLocal owner = new ThreadLocal() 60 * { 61 * public Object initialValue() 62 * { 63 * return("nobody"); 64 * } 65 * }; 66 * ... 67 * } 68 * </pre></br> 69 * 70 * Now all instances of connection can see who the owner of the currently 71 * executing Thread is by calling <code>owner.get()</code>. By default any 72 * Thread would be associated with 'nobody'. But the Connection object could 73 * offer a method that changes the owner associated with the Thread on 74 * which the method was called by calling <code>owner.put("somebody")</code>. 75 * (Such an owner changing method should then be guarded by security checks.) 76 * 77 * <p>When a Thread is garbage collected all references to values of 78 * the ThreadLocal objects associated with that Thread are removed. 79 * 80 * @author Mark Wielaard <mark@klomp.org> 81 * @author Eric Blake <ebb9@email.byu.edu> 82 * @since 1.2 83 * @status updated to 1.4 84 */ 85 public class ThreadLocal 86 { 87 /** 88 * Placeholder to distinguish between uninitialized and null set by the 89 * user. Do not expose this to the public. Package visible for use by 90 * InheritableThreadLocal 91 */ 92 static final Object NULL = new Object(); 93 94 /** 95 * The stored value. Package visible for use by InheritableThreadLocal. */ 96 Object value; 97 98 /** 99 * Maps Threads to values. Uses a WeakHashMap so if a Thread is garbage 100 * collected the reference to the Value will disappear. A null value means 101 * uninitialized, while NULL means a user-specified null. Only the 102 * <code>set(Thread, Object)</code> and <code>get(Thread)</code> methods 103 * access it. Package visible for use by InheritableThreadLocal. 104 */ 105 final Map valueMap = Collections.synchronizedMap(new WeakHashMap()); 106 107 /** 108 * Creates a ThreadLocal object without associating any value to it yet. 109 */ ThreadLocal()110 public ThreadLocal() 111 { 112 } 113 114 /** 115 * Called once per thread on the first invocation of get(), if set() was 116 * not already called. The default implementation returns <code>null</code>. 117 * Often, this method is overridden to create the appropriate initial object 118 * for the current thread's view of the ThreadLocal. 119 * 120 * @return the initial value of the variable in this thread 121 */ initialValue()122 protected Object initialValue() 123 { 124 return null; 125 } 126 127 /** 128 * Gets the value associated with the ThreadLocal object for the currently 129 * executing Thread. If this is the first time the current thread has called 130 * get(), and it has not already called set(), the value is obtained by 131 * <code>initialValue()</code>. 132 * 133 * @return the value of the variable in this thread 134 */ get()135 public Object get() 136 { 137 Thread currentThread = Thread.currentThread(); 138 // Note that we don't have to synchronize, as only this thread will 139 // ever modify the returned value and valueMap is a synchronizedMap. 140 Object value = valueMap.get(currentThread); 141 if (value == null) 142 { 143 value = initialValue(); 144 valueMap.put(currentThread, value == null ? NULL : value); 145 } 146 return value == NULL ? null : value; 147 } 148 149 /** 150 * Sets the value associated with the ThreadLocal object for the currently 151 * executing Thread. This overrides any existing value associated with the 152 * current Thread and prevents <code>initialValue()</code> from being 153 * called if this is the first access to this ThreadLocal in this Thread. 154 * 155 * @param value the value to set this thread's view of the variable to 156 */ set(Object value)157 public void set(Object value) 158 { 159 // Note that we don't have to synchronize, as only this thread will 160 // ever modify the returned value and valueMap is a synchronizedMap. 161 valueMap.put(Thread.currentThread(), value == null ? NULL : value); 162 } 163 } 164