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