|
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_ |