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