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