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