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