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