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 NativeBackendKWallet; 22class ScopedAllowWaitForLegacyWebViewApi; 23class TestingAutomationProvider; 24 25namespace browser_sync { 26class NonFrontendDataTypeController; 27class UIModelWorker; 28} 29namespace cc { 30class CompletionEvent; 31} 32namespace chromeos { 33class AudioMixerAlsa; 34class BlockingMethodCaller; 35namespace system { 36class StatisticsProviderImpl; 37} 38} 39namespace chrome_browser_net { 40class Predictor; 41} 42namespace content { 43class BrowserGpuChannelHostFactory; 44class BrowserShutdownProfileDumper; 45class BrowserTestBase; 46class GLHelper; 47class GpuChannelHost; 48class NestedMessagePumpAndroid; 49class RenderWidgetResizeHelper; 50class ScopedAllowWaitForAndroidLayoutTests; 51class TextInputClientMac; 52} 53namespace dbus { 54class Bus; 55} 56namespace disk_cache { 57class BackendImpl; 58class InFlightIO; 59} 60namespace media { 61class AudioOutputController; 62} 63namespace metrics { 64class MetricsService; 65} 66namespace mojo { 67namespace common { 68class WatcherThreadManager; 69} 70} 71namespace net { 72class FileStreamPosix; 73class FileStreamWin; 74namespace internal { 75class AddressTrackerLinux; 76} 77} 78 79namespace remoting { 80class AutoThread; 81} 82 83namespace base { 84 85namespace android { 86class JavaHandlerThread; 87} 88 89class SequencedWorkerPool; 90class SimpleThread; 91class Thread; 92class 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 119class 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: 125 ScopedAllowIO() { previous_value_ = SetIOAllowed(true); } 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: 138 ScopedAllowSingleton() { previous_value_ = SetSingletonAllowed(true); } 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. 176 static bool SetIOAllowed(bool allowed) { return true; } 177 static void AssertIOAllowed() {} 178 static bool SetSingletonAllowed(bool allowed) { return true; } 179 static void AssertSingletonAllowed() {} 180 static void DisallowWaiting() {} 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 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: 244 ScopedAllowWait() { previous_value_ = SetWaitAllowed(true); } 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