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