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