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