1 package jdk.internal.misc;
   2 
   3 import java.util.Arrays;
   4 import java.util.function.Consumer;
   5 
   6 public class JdkThreadLocal<T> extends ThreadLocal<T> {
   7     protected void threadTerminated(T value) {
   8     }
   9 
  10     public void callThreadTerminated(Object value) {
  11         @SuppressWarnings("unchecked")
  12         final T v = (T) value;
  13         threadTerminated(v);
  14     }
  15 
  16     public JdkThreadLocal() {
  17         add(this);
  18     }
  19 
  20     private static final class Entry<U> {
  21         private final JdkThreadLocal<U> threadLocal;
  22 
  23         private Entry(JdkThreadLocal<U> threadLocal) {
  24             this.threadLocal = threadLocal;
  25         }
  26 
  27         public JdkThreadLocal<U> threadLocal() {
  28             return threadLocal;
  29         }
  30     }
  31 
  32     private static volatile Entry<?>[] entries = new Entry<?>[0];
  33 
  34     private static synchronized <U> void add(JdkThreadLocal<U> threadLocal) {
  35         if (threadLocal == null) {
  36             throw new IllegalArgumentException("threadLocal is null");
  37         }
  38         forEach(tl -> {
  39             if (tl == threadLocal) {
  40                 throw new IllegalArgumentException("threadLocal has already been added");
  41             }
  42         });
  43 
  44         final Entry<U> entry = new Entry<>(threadLocal);
  45         final Entry<?>[] entries0 = Arrays.copyOf(entries, entries.length + 1);
  46         entries0[entries0.length - 1] = entry;
  47         entries = entries0;
  48     }
  49 
  50     public static void forEach(Consumer<JdkThreadLocal<?>> f) {
  51         final Entry<?>[] entries0 = entries;
  52         for (Entry<?> e: entries0) {
  53             final JdkThreadLocal<?> tl = e.threadLocal();
  54             f.accept(tl);
  55         }
  56     }
  57 }