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