source: trunk/src/gcc/libjava/java/lang/InheritableThreadLocal.java@ 1389

Last change on this file since 1389 was 2, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 6.0 KB
Line 
1/* java.lang.InheritableThreadLocal
2 Copyright (C) 2000, 2001 Free Software Foundation, Inc.
3
4This file is part of GNU Classpath.
5
6GNU Classpath is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Classpath is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Classpath; see the file COPYING. If not, write to the
18Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1902111-1307 USA.
20
21Linking this library statically or dynamically with other modules is
22making a combined work based on this library. Thus, the terms and
23conditions of the GNU General Public License cover the whole
24combination.
25
26As a special exception, the copyright holders of this library give you
27permission to link this library with independent modules to produce an
28executable, regardless of the license terms of these independent
29modules, and to copy and distribute the resulting executable under
30terms of your choice, provided that you also meet, for each linked
31independent module, the terms and conditions of the license of that
32module. An independent module is a module which is not derived from
33or based on this library. If you modify this library, you may extend
34this exception to your version of the library, but you are not
35obligated to do so. If you do not wish to do so, delete this
36exception statement from your version. */
37
38package java.lang;
39
40import java.util.Iterator;
41import java.util.HashSet;
42import java.util.Map;
43import java.util.Set;
44import java.util.WeakHashMap;
45
46/**
47 * ThreadLocal whose value is inherited by child Threads.
48 * The value of the InheritableThreadLocal associated with the (parent) Thread
49 * on the moment that it creates a new (child) Thread is set as the value that
50 * is associated with the new (child) Thread.
51 * <p>
52 * It is possible to make the value associated with the child Thread a function
53 * of the value that is associated with the parent Thread by overriding the
54 * <code>childValue()</code> method.
55 *
56 * @since 1.2
57 * @author Mark Wielaard ([email protected])
58 */
59public class InheritableThreadLocal extends ThreadLocal {
60
61 /**
62 * Maps Threads to a Set of InheritableThreadLocals
63 * (the heritage of that Thread).
64 * Uses a WeakHashMap so if the Thread is garbage collected the reference
65 * to that Set disappears.
66 * Both <code>AddToHeritage</code> access and modify it so they have to
67 * synchronize on the threadMap when they do.
68 */
69 private static Map threadMap = new WeakHashMap();
70
71 /**
72 * Creates a new InheritableThreadLocal that has no values associated
73 * with it yet.
74 */
75 public InheritableThreadLocal() {
76 super();
77 }
78
79 /**
80 * Determines the value associated with a newly created child Thread
81 * as a function of the value associated with the currently executing
82 * (parent) Thread.
83 * <p>
84 * The default implementation just returns the parentValue.
85 */
86 protected Object childValue(Object parentValue) {
87 return parentValue;
88 }
89
90 /**
91 * Adds this <code>InheritableThreadLocal</code> to the heritage of the
92 * current Thread and returns the value of the <code>ThreadLocal</code>
93 * for the Thread. The value will be either the last value that the
94 * current Thread has set, or the childValue of the last value that the
95 * parent Thread set before the current Thread was created, or the
96 * initialValue of the <code>ThreadLocal</code>.
97 *
98 * @see ThreadLocal#get()
99 */
100 public Object get() {
101 addToHeritage();
102 return super.get();
103 }
104
105 /**
106 * Adds this <code>InheritableThreadLocal</code> to the heritage of the
107 * current Thread and sets the value of the <code>ThreadLocal</code>
108 * for the Thread.
109 *
110 * @see ThreadLocal#set(Object)
111 */
112 public void set(Object value) {
113 addToHeritage();
114 super.set(value);
115 }
116
117 /**
118 * Adds this <code>InheritableThreadLocal</code> to the heritage
119 * of the current Thread.
120 */
121 private void addToHeritage() {
122 Thread currentThread = Thread.currentThread();
123 Set heritage;
124 synchronized(threadMap) {
125 heritage = (Set)threadMap.get(currentThread);
126 }
127 // Note that we don't have to synchronize on the heritage Set
128 // since only this Thread (or the parent Thread when creating
129 // the heritage) ever modifies it.
130 if (heritage == null) {
131 heritage = new HashSet();
132 synchronized(threadMap) {
133 threadMap.put(currentThread, heritage);
134 }
135 }
136 if (!heritage.contains(this)) {
137 heritage.add(this);
138 }
139 }
140
141 /**
142 * Generates the childValues of all <code>InheritableThreadLocal</code>s
143 * that are in the heritage of the current Thread for the newly created
144 * childThread.
145 * Should be called from the contructor of java.lang.Thread.
146 */
147 static void newChildThread(Thread childThread) {
148 // The currentThread is the parent of the new thread
149 Thread parentThread = Thread.currentThread();
150
151 // Inherit all the InheritableThreadLocals of the parent thread
152 Set heritage;
153 synchronized(threadMap) {
154 heritage = (Set)threadMap.get(parentThread);
155 }
156 // Note that we don't have to synchronize on the heritage Set
157 // since only this Thread (or the parent Thread when creating
158 // the heritage) ever modifies it.
159 if (heritage != null) {
160 synchronized(threadMap) {
161 threadMap.put(childThread, new HashSet(heritage));
162 }
163 // And constructs all the new child values
164 // (has to be done now that we are executing in the parentThread)
165 Iterator it = heritage.iterator();
166 while (it.hasNext()) {
167 InheritableThreadLocal local =
168 (InheritableThreadLocal) it.next();
169 // Note that the parentValue cannot be null
170 // If it was it would not be in the heritage
171 Object parentValue = local.get(parentThread).getValue();
172 Object childValue = local.childValue(parentValue);
173 ThreadLocal.Value v = new ThreadLocal.Value(childValue);
174 local.set(childThread, v);
175 }
176 }
177 }
178}
Note: See TracBrowser for help on using the repository browser.