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