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.netty.util.concurrent;
17  
18  import io.netty.util.internal.InternalThreadLocalMap;
19  import io.netty.util.internal.logging.InternalLogger;
20  import io.netty.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      public 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      public 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     public boolean willCleanupFastThreadLocals() {
101         return cleanupFastThreadLocals;
102     }
103 
104     /**
105      * Returns {@code true} if {@link FastThreadLocal#removeAll()} will be called once {@link Thread#run()} completes.
106      */
107     public static boolean willCleanupFastThreadLocals(Thread thread) {
108         return thread instanceof FastThreadLocalThread &&
109                 ((FastThreadLocalThread) thread).willCleanupFastThreadLocals();
110     }
111 
112     /**
113      * Query whether this thread is allowed to perform blocking calls or not.
114      * {@link FastThreadLocalThread}s are often used in event-loops, where blocking calls are forbidden in order to
115      * prevent event-loop stalls, so this method returns {@code false} by default.
116      * <p>
117      * Subclasses of {@link FastThreadLocalThread} can override this method if they are not meant to be used for
118      * running event-loops.
119      *
120      * @return {@code false}, unless overriden by a subclass.
121      */
122     public boolean permitBlockingCalls() {
123         return false;
124     }
125 }