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/logging.h" 10 #include "base/macros.h" 11 12 class BrowserProcessImpl; 13 class HistogramSynchronizer; 14 class NativeBackendKWallet; 15 class ScopedAllowWaitForLegacyWebViewApi; 16 17 namespace cc { 18 class CompletionEvent; 19 class SingleThreadTaskGraphRunner; 20 } 21 namespace chromeos { 22 class BlockingMethodCaller; 23 namespace system { 24 class StatisticsProviderImpl; 25 } 26 } 27 namespace chrome_browser_net { 28 class Predictor; 29 } 30 namespace content { 31 class BrowserGpuChannelHostFactory; 32 class BrowserGpuMemoryBufferManager; 33 class BrowserShutdownProfileDumper; 34 class BrowserSurfaceViewManager; 35 class BrowserTestBase; 36 class NestedMessagePumpAndroid; 37 class ScopedAllowWaitForAndroidLayoutTests; 38 class ScopedAllowWaitForDebugURL; 39 class SoftwareOutputDeviceMus; 40 class TextInputClientMac; 41 class CategorizedWorkerPool; 42 } // namespace content 43 namespace dbus { 44 class Bus; 45 } 46 namespace disk_cache { 47 class BackendImpl; 48 class InFlightIO; 49 } 50 namespace gpu { 51 class GpuChannelHost; 52 } 53 namespace mojo { 54 class SyncCallRestrictions; 55 namespace edk { 56 class ScopedIPCSupport; 57 } 58 } 59 namespace ui { 60 class CommandBufferClientImpl; 61 class CommandBufferLocal; 62 class GpuState; 63 } 64 namespace net { 65 class NetworkChangeNotifierMac; 66 namespace internal { 67 class AddressTrackerLinux; 68 } 69 } 70 71 namespace remoting { 72 class AutoThread; 73 } 74 75 namespace ui { 76 class WindowResizeHelperMac; 77 } 78 79 namespace views { 80 class ScreenMus; 81 } 82 83 namespace base { 84 85 namespace android { 86 class JavaHandlerThread; 87 } 88 89 namespace internal { 90 class TaskTracker; 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 #if DCHECK_IS_ON() 139 // Set whether the current thread to make IO calls. 140 // Threads start out in the *allowed* state. 141 // Returns the previous value. 142 static bool SetIOAllowed(bool allowed); 143 144 // Check whether the current thread is allowed to make IO calls, 145 // and DCHECK if not. See the block comment above the class for 146 // a discussion of where to add these checks. 147 static void AssertIOAllowed(); 148 149 // Set whether the current thread can use singletons. Returns the previous 150 // value. 151 static bool SetSingletonAllowed(bool allowed); 152 153 // Check whether the current thread is allowed to use singletons (Singleton / 154 // LazyInstance). DCHECKs if not. 155 static void AssertSingletonAllowed(); 156 157 // Disable waiting on the current thread. Threads start out in the *allowed* 158 // state. Returns the previous value. 159 static void DisallowWaiting(); 160 161 // Check whether the current thread is allowed to wait, and DCHECK if not. 162 static void AssertWaitAllowed(); 163 #else 164 // Inline the empty definitions of these functions so that they can be 165 // compiled out. SetIOAllowed(bool allowed)166 static bool SetIOAllowed(bool allowed) { return true; } AssertIOAllowed()167 static void AssertIOAllowed() {} SetSingletonAllowed(bool allowed)168 static bool SetSingletonAllowed(bool allowed) { return true; } AssertSingletonAllowed()169 static void AssertSingletonAllowed() {} DisallowWaiting()170 static void DisallowWaiting() {} AssertWaitAllowed()171 static void AssertWaitAllowed() {} 172 #endif 173 174 private: 175 // DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to jam or brettw first. 176 // BEGIN ALLOWED USAGE. 177 friend class content::BrowserShutdownProfileDumper; 178 friend class content::BrowserSurfaceViewManager; 179 friend class content::BrowserTestBase; 180 friend class content::NestedMessagePumpAndroid; 181 friend class content::ScopedAllowWaitForAndroidLayoutTests; 182 friend class content::ScopedAllowWaitForDebugURL; 183 friend class ::HistogramSynchronizer; 184 friend class internal::TaskTracker; 185 friend class ::ScopedAllowWaitForLegacyWebViewApi; 186 friend class cc::CompletionEvent; 187 friend class cc::SingleThreadTaskGraphRunner; 188 friend class content::CategorizedWorkerPool; 189 friend class remoting::AutoThread; 190 friend class ui::WindowResizeHelperMac; 191 friend class MessagePumpDefault; 192 friend class SequencedWorkerPool; 193 friend class SimpleThread; 194 friend class Thread; 195 friend class ThreadTestHelper; 196 friend class PlatformThread; 197 friend class android::JavaHandlerThread; 198 friend class mojo::SyncCallRestrictions; 199 friend class mojo::edk::ScopedIPCSupport; 200 friend class ui::CommandBufferClientImpl; 201 friend class ui::CommandBufferLocal; 202 friend class ui::GpuState; 203 204 // END ALLOWED USAGE. 205 // BEGIN USAGE THAT NEEDS TO BE FIXED. 206 friend class ::chromeos::BlockingMethodCaller; // http://crbug.com/125360 207 friend class ::chromeos::system::StatisticsProviderImpl; // http://crbug.com/125385 208 friend class chrome_browser_net::Predictor; // http://crbug.com/78451 209 friend class 210 content::BrowserGpuChannelHostFactory; // http://crbug.com/125248 211 friend class 212 content::BrowserGpuMemoryBufferManager; // http://crbug.com/420368 213 friend class content::TextInputClientMac; // http://crbug.com/121917 214 friend class dbus::Bus; // http://crbug.com/125222 215 friend class disk_cache::BackendImpl; // http://crbug.com/74623 216 friend class disk_cache::InFlightIO; // http://crbug.com/74623 217 friend class gpu::GpuChannelHost; // http://crbug.com/125264 218 friend class net::internal::AddressTrackerLinux; // http://crbug.com/125097 219 friend class net::NetworkChangeNotifierMac; // http://crbug.com/125097 220 friend class ::BrowserProcessImpl; // http://crbug.com/125207 221 friend class ::NativeBackendKWallet; // http://crbug.com/125331 222 #if !defined(OFFICIAL_BUILD) 223 friend class content::SoftwareOutputDeviceMus; // Interim non-production code 224 #endif 225 friend class views::ScreenMus; 226 // END USAGE THAT NEEDS TO BE FIXED. 227 228 #if DCHECK_IS_ON() 229 static bool SetWaitAllowed(bool allowed); 230 #else SetWaitAllowed(bool allowed)231 static bool SetWaitAllowed(bool allowed) { return true; } 232 #endif 233 234 // Constructing a ScopedAllowWait temporarily allows waiting on the current 235 // thread. Doing this is almost always incorrect, which is why we limit who 236 // can use this through friend. If you find yourself needing to use this, find 237 // another way. Talk to jam or brettw. 238 class BASE_EXPORT ScopedAllowWait { 239 public: ScopedAllowWait()240 ScopedAllowWait() { previous_value_ = SetWaitAllowed(true); } ~ScopedAllowWait()241 ~ScopedAllowWait() { SetWaitAllowed(previous_value_); } 242 private: 243 // Whether singleton use is allowed when the ScopedAllowWait was 244 // constructed. 245 bool previous_value_; 246 247 DISALLOW_COPY_AND_ASSIGN(ScopedAllowWait); 248 }; 249 250 DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions); 251 }; 252 253 } // namespace base 254 255 #endif // BASE_THREADING_THREAD_RESTRICTIONS_H_ 256