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