jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java
changeset 39723 9aa34e4a0469
parent 37521 b6e0f285c998
child 42322 c3474fef4fe4
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Fri Jul 15 13:51:43 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Fri Jul 15 13:55:51 2016 -0700
@@ -36,6 +36,7 @@
 package java.util.concurrent;
 
 import java.io.ObjectStreamField;
+import java.security.AccessControlContext;
 import java.util.Random;
 import java.util.Spliterator;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -47,6 +48,7 @@
 import java.util.stream.IntStream;
 import java.util.stream.LongStream;
 import java.util.stream.StreamSupport;
+import jdk.internal.misc.Unsafe;
 
 /**
  * A random number generator isolated to the current thread.  Like the
@@ -95,7 +97,9 @@
      * ThreadLocalRandom sequence.  The dual use is a marriage of
      * convenience, but is a simple and efficient way of reducing
      * application-level overhead and footprint of most concurrent
-     * programs.
+     * programs. Even more opportunistically, we also define here
+     * other package-private utilities that access Thread class
+     * fields.
      *
      * Even though this class subclasses java.util.Random, it uses the
      * same basic algorithm as java.util.SplittableRandom.  (See its
@@ -958,6 +962,49 @@
         return r;
     }
 
+    // Support for other package-private ThreadLocal access
+
+    /**
+     * Erases ThreadLocals by nulling out Thread maps.
+     */
+    static final void eraseThreadLocals(Thread thread) {
+        U.putObject(thread, THREADLOCALS, null);
+        U.putObject(thread, INHERITABLETHREADLOCALS, null);
+    }
+
+    static final void setInheritedAccessControlContext(Thread thread,
+                                                       AccessControlContext acc) {
+        U.putObjectRelease(thread, INHERITEDACCESSCONTROLCONTEXT, acc);
+    }
+
+    /**
+     * Returns a new group with the system ThreadGroup (the
+     * topmost, parent-less group) as parent.  Uses Unsafe to
+     * traverse Thread.group and ThreadGroup.parent fields.
+     */
+    static final ThreadGroup createThreadGroup(String name) {
+        if (name == null)
+            throw new NullPointerException();
+        try {
+            long tg = U.objectFieldOffset
+                (Thread.class.getDeclaredField("group"));
+            long gp = U.objectFieldOffset
+                (ThreadGroup.class.getDeclaredField("parent"));
+            ThreadGroup group = (ThreadGroup)
+                U.getObject(Thread.currentThread(), tg);
+            while (group != null) {
+                ThreadGroup parent = (ThreadGroup)U.getObject(group, gp);
+                if (parent == null)
+                    return new ThreadGroup(group, name);
+                group = parent;
+            }
+        } catch (ReflectiveOperationException e) {
+            throw new Error(e);
+        }
+        // fall through if null as cannot-happen safeguard
+        throw new Error("Cannot create ThreadGroup");
+    }
+
     // Serialization support
 
     private static final long serialVersionUID = -5851777807851030925L;
@@ -1022,10 +1069,13 @@
     static final String BAD_SIZE  = "size must be non-negative";
 
     // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+    private static final Unsafe U = Unsafe.getUnsafe();
     private static final long SEED;
     private static final long PROBE;
     private static final long SECONDARY;
+    private static final long THREADLOCALS;
+    private static final long INHERITABLETHREADLOCALS;
+    private static final long INHERITEDACCESSCONTROLCONTEXT;
     static {
         try {
             SEED = U.objectFieldOffset
@@ -1034,6 +1084,12 @@
                 (Thread.class.getDeclaredField("threadLocalRandomProbe"));
             SECONDARY = U.objectFieldOffset
                 (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+            THREADLOCALS = U.objectFieldOffset
+                (Thread.class.getDeclaredField("threadLocals"));
+            INHERITABLETHREADLOCALS = U.objectFieldOffset
+                (Thread.class.getDeclaredField("inheritableThreadLocals"));
+            INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
+                (Thread.class.getDeclaredField("inheritedAccessControlContext"));
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }