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.UnstableApi;
20  import io.netty.util.internal.logging.InternalLogger;
21  import io.netty.util.internal.logging.InternalLoggerFactory;
22  
23  /**
24   * A special {@link Thread} that provides fast access to {@link FastThreadLocal} variables.
25   */
26  public class FastThreadLocalThread extends Thread {
27  
28      private static final InternalLogger logger = InternalLoggerFactory.getInstance(FastThreadLocalThread.class);
29  
30      // This will be set to true if we have a chance to wrap the Runnable.
31      private final boolean cleanupFastThreadLocals;
32  
33      private InternalThreadLocalMap threadLocalMap;
34  
35      public FastThreadLocalThread() {
36          cleanupFastThreadLocals = false;
37      }
38  
39      public FastThreadLocalThread(Runnable target) {
40          super(FastThreadLocalRunnable.wrap(target));
41          cleanupFastThreadLocals = true;
42      }
43  
44      public FastThreadLocalThread(ThreadGroup group, Runnable target) {
45          super(group, FastThreadLocalRunnable.wrap(target));
46          cleanupFastThreadLocals = true;
47      }
48  
49      public FastThreadLocalThread(String name) {
50          super(name);
51          cleanupFastThreadLocals = false;
52      }
53  
54      public FastThreadLocalThread(ThreadGroup group, String name) {
55          super(group, name);
56          cleanupFastThreadLocals = false;
57      }
58  
59      public FastThreadLocalThread(Runnable target, String name) {
60          super(FastThreadLocalRunnable.wrap(target), name);
61          cleanupFastThreadLocals = true;
62      }
63  
64      public FastThreadLocalThread(ThreadGroup group, Runnable target, String name) {
65          super(group, FastThreadLocalRunnable.wrap(target), name);
66          cleanupFastThreadLocals = true;
67      }
68  
69      public FastThreadLocalThread(ThreadGroup group, Runnable target, String name, long stackSize) {
70          super(group, FastThreadLocalRunnable.wrap(target), name, stackSize);
71          cleanupFastThreadLocals = true;
72      }
73  
74      /**
75       * Returns the internal data structure that keeps the thread-local variables bound to this thread.
76       * Note that this method is for internal use only, and thus is subject to change at any time.
77       */
78      public final InternalThreadLocalMap threadLocalMap() {
79          if (this != Thread.currentThread() && logger.isWarnEnabled()) {
80              logger.warn(new RuntimeException("It's not thread-safe to get 'threadLocalMap' " +
81                      "which doesn't belong to the caller thread"));
82          }
83          return threadLocalMap;
84      }
85  
86      /**
87       * Sets the internal data structure that keeps the thread-local variables bound to this thread.
88       * Note that this method is for internal use only, and thus is subject to change at any time.
89       */
90      public final void setThreadLocalMap(InternalThreadLocalMap threadLocalMap) {
91          if (this != Thread.currentThread() && logger.isWarnEnabled()) {
92              logger.warn(new RuntimeException("It's not thread-safe to set 'threadLocalMap' " +
93                      "which doesn't belong to the caller thread"));
94          }
95          this.threadLocalMap = threadLocalMap;
96      }
97  
98      /**
99       * Returns {@code true} if {@link FastThreadLocal#removeAll()} will be called once {@link #run()} completes.
100      */
101     @UnstableApi
102     public boolean willCleanupFastThreadLocals() {
103         return cleanupFastThreadLocals;
104     }
105 
106     /**
107      * Returns {@code true} if {@link FastThreadLocal#removeAll()} will be called once {@link Thread#run()} completes.
108      */
109     @UnstableApi
110     public static boolean willCleanupFastThreadLocals(Thread thread) {
111         return thread instanceof FastThreadLocalThread &&
112                 ((FastThreadLocalThread) thread).willCleanupFastThreadLocals();
113     }
114 
115     /**
116      * Query whether this thread is allowed to perform blocking calls or not.
117      * {@link FastThreadLocalThread}s are often used in event-loops, where blocking calls are forbidden in order to
118      * prevent event-loop stalls, so this method returns {@code false} by default.
119      * <p>
120      * Subclasses of {@link FastThreadLocalThread} can override this method if they are not meant to be used for
121      * running event-loops.
122      *
123      * @return {@code false}, unless overriden by a subclass.
124      */
125     public boolean permitBlockingCalls() {
126         return false;
127     }
128 }