Makefile.am (core_java_source_files): add InheritableThreadLocal
authorMark Wielaard <mark@klomp.org>
Tue, 2 Oct 2001 22:49:59 +0000 (22:49 +0000)
committerMark Wielaard <mark@gcc.gnu.org>
Tue, 2 Oct 2001 22:49:59 +0000 (22:49 +0000)
* Makefile.am (core_java_source_files): add InheritableThreadLocal
* Makefile.in: regenerate
* gcj/javaprims.h: ditto
* java/lang/InheritableThreadLocal.java: new class from Classpath
* java/lang/Thread.java Thread (Thread, ThreadGroup, Runnable, String):
call InheritableThreadLocal.newChildThread()

From-SVN: r45979

libjava/ChangeLog
libjava/Makefile.am
libjava/Makefile.in
libjava/gcj/javaprims.h
libjava/java/lang/InheritableThreadLocal.java [new file with mode: 0644]
libjava/java/lang/Thread.java

index 8c1ce8707616fdcacf4cbaa2e5113e3ed9d473a9..84a61c2dca92915dbd29896aba9b6d162870e8c3 100644 (file)
@@ -1,3 +1,12 @@
+2001-10-02  Mark Wielaard  <mark@klomp.org>
+
+       * Makefile.am (core_java_source_files): add InheritableThreadLocal
+       * Makefile.in: regenerate
+       * gcj/javaprims.h: ditto
+       * java/lang/InheritableThreadLocal.java: new class from Classpath
+       * java/lang/Thread.java Thread (Thread, ThreadGroup, Runnable, String):
+       call InheritableThreadLocal.newChildThread()
+
 2001-10-01  Mark Wielaard  <mark@klomp.org>
 
        * Makefile.am: Add new classes
index 7eeb6d299f698528b518b87f5028814f43f335e3..91d437fed9db4df71e3ead6cfabf9db42c883083 100644 (file)
@@ -937,6 +937,7 @@ java/lang/IllegalStateException.java \
 java/lang/IllegalThreadStateException.java \
 java/lang/IncompatibleClassChangeError.java \
 java/lang/IndexOutOfBoundsException.java \
+java/lang/InheritableThreadLocal.java \
 java/lang/InstantiationError.java \
 java/lang/InstantiationException.java \
 java/lang/Integer.java \
index 1b8b9b32e466cd7b70e31bab6e9fe5439d39d05e..1c605a20e49a1b9667c111fa2d14db27842199d9 100644 (file)
@@ -668,6 +668,7 @@ java/lang/IllegalStateException.java \
 java/lang/IllegalThreadStateException.java \
 java/lang/IncompatibleClassChangeError.java \
 java/lang/IndexOutOfBoundsException.java \
+java/lang/InheritableThreadLocal.java \
 java/lang/InstantiationError.java \
 java/lang/InstantiationException.java \
 java/lang/Integer.java \
@@ -1793,6 +1794,7 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/java/lang/IllegalThreadStateException.P \
 .deps/java/lang/IncompatibleClassChangeError.P \
 .deps/java/lang/IndexOutOfBoundsException.P \
+.deps/java/lang/InheritableThreadLocal.P \
 .deps/java/lang/InstantiationError.P \
 .deps/java/lang/InstantiationException.P .deps/java/lang/Integer.P \
 .deps/java/lang/InternalError.P .deps/java/lang/InterruptedException.P \
index aa7c51e8e02497b4f6b223585b2f0caaf752a098..f9cac09f5f25948e613b3e7e59558d0ae5d50ff5 100644 (file)
@@ -162,6 +162,7 @@ extern "Java"
       class IllegalThreadStateException;
       class IncompatibleClassChangeError;
       class IndexOutOfBoundsException;
+      class InheritableThreadLocal;
       class InstantiationError;
       class InstantiationException;
       class Integer;
diff --git a/libjava/java/lang/InheritableThreadLocal.java b/libjava/java/lang/InheritableThreadLocal.java
new file mode 100644 (file)
index 0000000..32102a6
--- /dev/null
@@ -0,0 +1,167 @@
+/* java.lang.InheritableThreadLocal
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+package java.lang;
+
+import java.util.Iterator;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+/**
+ * ThreadLocal whose value is inherited by child Threads.
+ * The value of the InheritableThreadLocal associated with the (parent) Thread
+ * on the moment that it creates a new (child) Thread is set as the value that
+ * is associated with the new (child) Thread.
+ * <p>
+ * It is possible to make the value associated with the child Thread a function
+ * of the value that is associated with the parent Thread by overriding the
+ * <code>childValue()</code> method.
+ *
+ * @since 1.2
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public class InheritableThreadLocal extends ThreadLocal {
+       
+       /**
+        * Maps Threads to a Set of InheritableThreadLocals
+        * (the heritage of that Thread).
+        * Uses a WeakHashMap so if the Thread is garbage collected the reference
+        * to that Set disappears.
+        * Both <code>AddToHeritage</code> access and modify it so they have to
+        * synchronize on the threadMap when they do.
+        */
+       private static Map threadMap = new WeakHashMap();
+       
+       /**
+        * Creates a new InheritableThreadLocal that has no values associated
+        * with it yet.
+        */
+       public InheritableThreadLocal() {
+               super();
+       }
+       
+       /**
+        * Determines the value associated with a newly created child Thread
+        * as a function of the value associated with the currently executing
+        * (parent) Thread.
+        * <p>
+        * The default implementation just returns the parentValue.
+        */
+       protected Object childValue(Object parentValue) {
+               return parentValue;
+       }
+       
+       /**
+        * Adds this <code>InheritableThreadLocal</code> to the heritage of the
+        * current Thread and returns the value of the <code>ThreadLocal</code>
+        * for the Thread. The value will be either the last value that the
+        * current Thread has set, or the childValue of the last value that the
+        * parent Thread set before the current Thread was created, or the
+        * initialValue of the <code>ThreadLocal</code>.
+        *
+        * @see ThreadLocal#get()
+        */
+       public Object get() {
+               addToHeritage(); 
+               return super.get();
+       }
+       
+       /**
+        * Adds this <code>InheritableThreadLocal</code> to the heritage of the
+        * current Thread and sets the value of the <code>ThreadLocal</code>
+        * for the Thread.
+        *
+        * @see ThreadLocal#set(Object)
+        */
+       public void set(Object value) {
+               addToHeritage();
+               super.set(value);
+       }
+       
+       /**
+        * Adds this <code>InheritableThreadLocal</code> to the heritage
+        * of the current Thread.
+        */
+       private void addToHeritage() {
+               Thread currentThread = Thread.currentThread();
+               Set heritage;
+               synchronized(threadMap) {
+                       heritage = (Set)threadMap.get(currentThread);
+               }
+               // Note that we don't have to synchronize on the heritage Set
+               // since only this Thread (or the parent Thread when creating
+               // the heritage) ever modifies it.
+               if (heritage == null) {
+                       heritage = new HashSet();
+                       synchronized(threadMap) {
+                               threadMap.put(currentThread, heritage);
+                       }
+               }
+               if (!heritage.contains(this)) {
+                       heritage.add(this);
+               }
+       }
+       
+       /**
+        * Generates the childValues of all <code>InheritableThreadLocal</code>s
+        * that are in the heritage of the current Thread for the newly created
+        * childThread.
+        * Should be called from the contructor of java.lang.Thread.
+        */
+       static void newChildThread(Thread childThread) {
+               // The currentThread is the parent of the new thread
+               Thread parentThread = Thread.currentThread();
+               
+               // Inherit all the InheritableThreadLocals of the parent thread
+               Set heritage;
+               synchronized(threadMap) {
+                       heritage = (Set)threadMap.get(parentThread);
+               }
+               // Note that we don't have to synchronize on the heritage Set
+               // since only this Thread (or the parent Thread when creating
+               // the heritage) ever modifies it.
+               if (heritage != null) {
+                       synchronized(threadMap) {
+                               threadMap.put(childThread, new HashSet(heritage));
+                       }
+                       // And constructs all the new child values
+                       // (has to be done now that we are executing in the parentThread)
+                       Iterator it = heritage.iterator();
+                       while (it.hasNext()) {
+                               InheritableThreadLocal local =
+                                       (InheritableThreadLocal) it.next();
+                               // Note that the parentValue cannot be null
+                               // If it was it would not be in the heritage
+                               Object parentValue = local.get(parentThread).getValue();
+                               Object childValue = local.childValue(parentValue);
+                               ThreadLocal.Value v = new ThreadLocal.Value(childValue);
+                               local.set(childThread, v);
+                       }
+               }
+       }
+}
index 97833ddc60937755b77f4ea1a34b2492adab80a2..542f47192fda4c3e95e383f364795056c7091fa1 100644 (file)
@@ -247,6 +247,7 @@ public class Thread implements Runnable
        int pri = current.getPriority();
        priority = (gmax < pri ? gmax : pri);
        context_class_loader = current.context_class_loader;
+       InheritableThreadLocal.newChildThread(this);
       }
     else
       {