View Javadoc
1   /*
2   * Copyright 2014 The Netty Project
3   *
4   * The Netty Project licenses this file to you under the Apache License,
5   * version 2.0 (the "License"); you may not use this file except in compliance
6   * with the License. You may obtain a copy of the License at:
7   *
8   *   https://www.apache.org/licenses/LICENSE-2.0
9   *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */
16  package io.netty5.util.concurrent;
17  
18  import io.netty5.util.internal.UnstableApi;
19  import io.netty5.util.internal.logging.InternalLogger;
20  import io.netty5.util.internal.logging.InternalLoggerFactory;
21  
22  /**
23   * A special {@link Thread} that provides fast access to {@link FastThreadLocal} variables.
24   */
25  public class FastThreadLocalThread extends Thread {
26  
27      private static final InternalLogger logger = InternalLoggerFactory.getInstance(FastThreadLocalThread.class);
28  
29      // This will be set to true if we have a chance to wrap the Runnable.
30      private final boolean cleanupFastThreadLocals;
31  
32      private InternalThreadLocalMap threadLocalMap;
33  
34      public FastThreadLocalThread() {
35          cleanupFastThreadLocals = false;
36      }
37  
38      public FastThreadLocalThread(Runnable target) {
39          super(FastThreadLocalRunnable.wrap(target));
40          cleanupFastThreadLocals = true;
41      }
42  
43      public FastThreadLocalThread(ThreadGroup group, Runnable target) {
44          super(group, FastThreadLocalRunnable.wrap(target));
45          cleanupFastThreadLocals = true;
46      }
47  
48      public FastThreadLocalThread(String name) {
49          super(name);
50          cleanupFastThreadLocals = false;
51      }
52  
53      public FastThreadLocalThread(ThreadGroup group, String name) {
54          super(group, name);
55          cleanupFastThreadLocals = false;
56      }
57  
58      public FastThreadLocalThread(Runnable target, String name) {
59          super(FastThreadLocalRunnable.wrap(target), name);
60          cleanupFastThreadLocals = true;
61      }
62  
63      public FastThreadLocalThread(ThreadGroup group, Runnable target, String name) {
64          super(group, FastThreadLocalRunnable.wrap(target), name);
65          cleanupFastThreadLocals = true;
66      }
67  
68      public FastThreadLocalThread(ThreadGroup group, Runnable target, String name, long stackSize) {
69          super(group, FastThreadLocalRunnable.wrap(target), name, stackSize);
70          cleanupFastThreadLocals = true;
71      }
72  
73      /**
74       * Returns the internal data structure that keeps the thread-local variables bound to this thread.
75       * Note that this method is for internal use only, and thus is subject to change at any time.
76       */
77      final InternalThreadLocalMap threadLocalMap() {
78          if (this != Thread.currentThread() && logger.isWarnEnabled()) {
79              logger.warn(new RuntimeException("It's not thread-safe to get 'threadLocalMap' " +
80                      "which doesn't belong to the caller thread"));
81          }
82          return threadLocalMap;
83      }
84  
85      /**
86       * Sets the internal data structure that keeps the thread-local variables bound to this thread.
87       * Note that this method is for internal use only, and thus is subject to change at any time.
88       */
89      final void setThreadLocalMap(InternalThreadLocalMap threadLocalMap) {
90          if (this != Thread.currentThread() && logger.isWarnEnabled()) {
91              logger.warn(new RuntimeException("It's not thread-safe to set 'threadLocalMap' " +
92                      "which doesn't belong to the caller thread"));
93          }
94          this.threadLocalMap = threadLocalMap;
95      }
96  
97      /**
98       * Returns {@code true} if {@link FastThreadLocal#removeAll()} will be called once {@link #run()} completes.
99       */
100     @UnstableApi
101     public boolean willCleanupFastThreadLocals() {
102         return cleanupFastThreadLocals;
103     }
104 
105     /**
106      * Returns {@code true} if {@link FastThreadLocal#removeAll()} will be called once {@link Thread#run()} completes.
107      */
108     @UnstableApi
109     public static boolean willCleanupFastThreadLocals(Thread thread) {
110         return thread instanceof FastThreadLocalThread &&
111                 ((FastThreadLocalThread) thread).willCleanupFastThreadLocals();
112     }
113 }