1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_THREADING_THREAD_RESTRICTIONS_H_ 6 #define BASE_THREADING_THREAD_RESTRICTIONS_H_ 7 8 #include "base/base_export.h" 9 #include "base/macros.h" 10 11 // See comment at top of thread_checker.h 12 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) 13 #define ENABLE_THREAD_RESTRICTIONS 1 14 #else 15 #define ENABLE_THREAD_RESTRICTIONS 0 16 #endif 17 18 class BrowserProcessImpl; 19 class HistogramSynchronizer; 20 class NativeBackendKWallet; 21 class ScopedAllowWaitForLegacyWebViewApi; 22 23 namespace cc { 24 class CompletionEvent; 25 class SingleThreadTaskGraphRunner; 26 } 27 namespace chromeos { 28 class BlockingMethodCaller; 29 namespace system { 30 class StatisticsProviderImpl; 31 } 32 } 33 namespace chrome_browser_net { 34 class Predictor; 35 } 36 namespace content { 37 class BrowserGpuChannelHostFactory; 38 class BrowserGpuMemoryBufferManager; 39 class BrowserShutdownProfileDumper; 40 class BrowserTestBase; 41 class GpuChannelHost; 42 class NestedMessagePumpAndroid; 43 class ScopedAllowWaitForAndroidLayoutTests; 44 class ScopedAllowWaitForDebugURL; 45 class SoftwareOutputDeviceMus; 46 class TextInputClientMac; 47 class RasterWorkerPool; 48 } // namespace content 49 namespace dbus { 50 class Bus; 51 } 52 namespace disk_cache { 53 class BackendImpl; 54 class InFlightIO; 55 } 56 namespace gles2 { 57 class CommandBufferClientImpl; 58 } 59 namespace mojo { 60 namespace common { 61 class MessagePumpMojo; 62 } 63 } 64 namespace mus { 65 class CommandBufferLocal; 66 class GpuState; 67 } 68 namespace net { 69 class NetworkChangeNotifierMac; 70 namespace internal { 71 class AddressTrackerLinux; 72 } 73 } 74 75 namespace remoting { 76 class AutoThread; 77 } 78 79 namespace ui { 80 class WindowResizeHelperMac; 81 } 82 83 namespace views { 84 class WindowManagerConnection; 85 } 86 87 namespace base { 88 89 namespace android { 90 class JavaHandlerThread; 91 } 92 93 class SequencedWorkerPool; 94 class SimpleThread; 95 class Thread; 96 class ThreadTestHelper; 97 98 // Certain behavior is disallowed on certain threads. ThreadRestrictions helps 99 // enforce these rules. Examples of such rules: 100 // 101 // * Do not do blocking IO (makes the thread janky) 102 // * Do not access Singleton/LazyInstance (may lead to shutdown crashes) 103 // 104 // Here's more about how the protection works: 105 // 106 // 1) If a thread should not be allowed to make IO calls, mark it: 107 // base::ThreadRestrictions::SetIOAllowed(false); 108 // By default, threads *are* allowed to make IO calls. 109 // In Chrome browser code, IO calls should be proxied to the File thread. 110 // 111 // 2) If a function makes a call that will go out to disk, check whether the 112 // current thread is allowed: 113 // base::ThreadRestrictions::AssertIOAllowed(); 114 // 115 // 116 // Style tip: where should you put AssertIOAllowed checks? It's best 117 // if you put them as close to the disk access as possible, at the 118 // lowest level. This rule is simple to follow and helps catch all 119 // callers. For example, if your function GoDoSomeBlockingDiskCall() 120 // only calls other functions in Chrome and not fopen(), you should go 121 // add the AssertIOAllowed checks in the helper functions. 122 123 class BASE_EXPORT ThreadRestrictions { 124 public: 125 // Constructing a ScopedAllowIO temporarily allows IO for the current 126 // thread. Doing this is almost certainly always incorrect. 127 class BASE_EXPORT ScopedAllowIO { 128 public: ScopedAllowIO()129 ScopedAllowIO() { previous_value_ = SetIOAllowed(true); } ~ScopedAllowIO()130 ~ScopedAllowIO() { SetIOAllowed(previous_value_); } 131 private: 132 // Whether IO is allowed when the ScopedAllowIO was constructed. 133 bool previous_value_; 134 135 DISALLOW_COPY_AND_ASSIGN(ScopedAllowIO); 136 }; 137 138 // Constructing a ScopedAllowSingleton temporarily allows accessing for the 139 // current thread. Doing this is almost always incorrect. 140 class BASE_EXPORT ScopedAllowSingleton { 141 public: ScopedAllowSingleton()142 ScopedAllowSingleton() { previous_value_ = SetSingletonAllowed(true); } ~ScopedAllowSingleton()143 ~ScopedAllowSingleton() { SetSingletonAllowed(previous_value_); } 144 private: 145 // Whether singleton use is allowed when the ScopedAllowSingleton was 146 // constructed. 147 bool previous_value_; 148 149 DISALLOW_COPY_AND_ASSIGN(ScopedAllowSingleton); 150 }; 151 152 #if ENABLE_THREAD_RESTRICTIONS 153 // Set whether the current thread to make IO calls. 154 // Threads start out in the *allowed* state. 155 // Returns the previous value. 156 static bool SetIOAllowed(bool allowed); 157 158 // Check whether the current thread is allowed to make IO calls, 159 // and DCHECK if not. See the block comment above the class for 160 // a discussion of where to add these checks. 161 static void AssertIOAllowed(); 162 163 // Set whether the current thread can use singletons. Returns the previous 164 // value. 165 static bool SetSingletonAllowed(bool allowed); 166 167 // Check whether the current thread is allowed to use singletons (Singleton / 168 // LazyInstance). DCHECKs if not. 169 static void AssertSingletonAllowed(); 170 171 // Disable waiting on the current thread. Threads start out in the *allowed* 172 // state. Returns the previous value. 173 static void DisallowWaiting(); 174 175 // Check whether the current thread is allowed to wait, and DCHECK if not. 176 static void AssertWaitAllowed(); 177 #else 178 // Inline the empty definitions of these functions so that they can be 179 // compiled out. SetIOAllowed(bool)180 static bool SetIOAllowed(bool /* allowed */) { return true; } AssertIOAllowed()181 static void AssertIOAllowed() {} SetSingletonAllowed(bool)182 static bool SetSingletonAllowed(bool /* allowed */) { return true; } AssertSingletonAllowed()183 static void AssertSingletonAllowed() {} DisallowWaiting()184 static void DisallowWaiting() {} AssertWaitAllowed()185 static void AssertWaitAllowed() {} 186 #endif 187 188 private: 189 // DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to jam or brettw first. 190 // BEGIN ALLOWED USAGE. 191 friend class content::BrowserShutdownProfileDumper; 192 friend class content::BrowserTestBase; 193 friend class content::NestedMessagePumpAndroid; 194 friend class content::ScopedAllowWaitForAndroidLayoutTests; 195 friend class content::ScopedAllowWaitForDebugURL; 196 friend class ::HistogramSynchronizer; 197 friend class ::ScopedAllowWaitForLegacyWebViewApi; 198 friend class cc::CompletionEvent; 199 friend class cc::SingleThreadTaskGraphRunner; 200 friend class content::RasterWorkerPool; 201 friend class remoting::AutoThread; 202 friend class ui::WindowResizeHelperMac; 203 friend class MessagePumpDefault; 204 friend class SequencedWorkerPool; 205 friend class SimpleThread; 206 friend class Thread; 207 friend class ThreadTestHelper; 208 friend class PlatformThread; 209 friend class android::JavaHandlerThread; 210 friend class gles2::CommandBufferClientImpl; 211 friend class mojo::common::MessagePumpMojo; 212 friend class mus::CommandBufferLocal; 213 friend class mus::GpuState; 214 215 // END ALLOWED USAGE. 216 // BEGIN USAGE THAT NEEDS TO BE FIXED. 217 friend class ::chromeos::BlockingMethodCaller; // http://crbug.com/125360 218 friend class ::chromeos::system::StatisticsProviderImpl; // http://crbug.com/125385 219 friend class chrome_browser_net::Predictor; // http://crbug.com/78451 220 friend class 221 content::BrowserGpuChannelHostFactory; // http://crbug.com/125248 222 friend class 223 content::BrowserGpuMemoryBufferManager; // http://crbug.com/420368 224 friend class content::GpuChannelHost; // http://crbug.com/125264 225 friend class content::TextInputClientMac; // http://crbug.com/121917 226 friend class dbus::Bus; // http://crbug.com/125222 227 friend class disk_cache::BackendImpl; // http://crbug.com/74623 228 friend class disk_cache::InFlightIO; // http://crbug.com/74623 229 friend class net::internal::AddressTrackerLinux; // http://crbug.com/125097 230 friend class net::NetworkChangeNotifierMac; // http://crbug.com/125097 231 friend class ::BrowserProcessImpl; // http://crbug.com/125207 232 friend class ::NativeBackendKWallet; // http://crbug.com/125331 233 #if !defined(OFFICIAL_BUILD) 234 friend class content::SoftwareOutputDeviceMus; // Interim non-production code 235 #endif 236 friend class views::WindowManagerConnection; 237 // END USAGE THAT NEEDS TO BE FIXED. 238 239 #if ENABLE_THREAD_RESTRICTIONS 240 static bool SetWaitAllowed(bool allowed); 241 #else SetWaitAllowed(bool)242 static bool SetWaitAllowed(bool /* allowed */) { return true; } 243 #endif 244 245 // Constructing a ScopedAllowWait temporarily allows waiting on the current 246 // thread. Doing this is almost always incorrect, which is why we limit who 247 // can use this through friend. If you find yourself needing to use this, find 248 // another way. Talk to jam or brettw. 249 class BASE_EXPORT ScopedAllowWait { 250 public: ScopedAllowWait()251 ScopedAllowWait() { previous_value_ = SetWaitAllowed(true); } ~ScopedAllowWait()252 ~ScopedAllowWait() { SetWaitAllowed(previous_value_); } 253 private: 254 // Whether singleton use is allowed when the ScopedAllowWait was 255 // constructed. 256 bool previous_value_; 257 258 DISALLOW_COPY_AND_ASSIGN(ScopedAllowWait); 259 }; 260 261 DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions); 262 }; 263 264 } // namespace base 265 266 #endif // BASE_THREADING_THREAD_RESTRICTIONS_H_ 267