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