thread_restrictions.h revision 116680a4aac90f2aa7413d9095a592090648e557
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 net {
65class FileStreamPosix;
66class FileStreamWin;
67namespace internal {
68class AddressTrackerLinux;
69}
70}
71
72namespace remoting {
73class AutoThread;
74}
75
76namespace base {
77
78namespace android {
79class JavaHandlerThread;
80}
81
82class SequencedWorkerPool;
83class SimpleThread;
84class Thread;
85class 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
112class 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:
118    ScopedAllowIO() { previous_value_ = SetIOAllowed(true); }
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:
131    ScopedAllowSingleton() { previous_value_ = SetSingletonAllowed(true); }
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.
169  static bool SetIOAllowed(bool allowed) { return true; }
170  static void AssertIOAllowed() {}
171  static bool SetSingletonAllowed(bool allowed) { return true; }
172  static void AssertSingletonAllowed() {}
173  static void DisallowWaiting() {}
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::RenderWidgetResizeHelper;
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
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:
236    ScopedAllowWait() { previous_value_ = SetWaitAllowed(true); }
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