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/gtest_prod_util.h"
10 #include "base/logging.h"
11 #include "base/macros.h"
12 
13 // -----------------------------------------------------------------------------
14 // Usage documentation
15 // -----------------------------------------------------------------------------
16 //
17 // Overview:
18 // This file exposes functions to ban and allow certain slow operations
19 // on a per-thread basis. To annotate *usage* of such slow operations, refer to
20 // scoped_blocking_call.h instead.
21 //
22 // Specific allowances that can be controlled in this file are:
23 // - Blocking call: Refers to any call that causes the calling thread to wait
24 //   off-CPU. It includes but is not limited to calls that wait on synchronous
25 //   file I/O operations: read or write a file from disk, interact with a pipe
26 //   or a socket, rename or delete a file, enumerate files in a directory, etc.
27 //   Acquiring a low contention lock is not considered a blocking call.
28 //
29 // - Waiting on a //base sync primitive: Refers to calling one of these methods:
30 //   - base::WaitableEvent::*Wait*
31 //   - base::ConditionVariable::*Wait*
32 //   - base::Process::WaitForExit*
33 //
34 // - Long CPU work: Refers to any code that takes more than 100 ms to
35 //   run when there is no CPU contention and no hard page faults and therefore,
36 //   is not suitable to run on a thread required to keep the browser responsive
37 //   (where jank could be visible to the user).
38 //
39 // The following disallowance functions are offered:
40 //  - DisallowBlocking(): Disallows blocking calls on the current thread.
41 //  - DisallowBaseSyncPrimitives(): Disallows waiting on a //base sync primitive
42 //    on the current thread.
43 //  - DisallowUnresponsiveTasks() Disallows blocking calls, waiting on a //base
44 //    sync primitive, and long cpu work on the current thread.
45 //
46 // In addition, scoped-allowance mechanisms are offered to make an exception
47 // within a scope for a behavior that is normally disallowed.
48 //  - ScopedAllowBlocking(ForTesting): Allows blocking calls.
49 //  - ScopedAllowBaseSyncPrimitives(ForTesting)(OutsideBlockingScope): Allow
50 //    waiting on a //base sync primitive. The OutsideBlockingScope suffix allows
51 //    uses in a scope where blocking is also disallowed.
52 //
53 // Avoid using allowances outside of unit tests. In unit tests, use allowances
54 // with the suffix "ForTesting".
55 //
56 // Prefer making blocking calls from tasks posted to base::ThreadPoolInstance
57 // with base::MayBlock().
58 //
59 // Instead of waiting on a WaitableEvent or a ConditionVariable, prefer putting
60 // the work that should happen after the wait in a continuation callback and
61 // post it from where the WaitableEvent or ConditionVariable would have been
62 // signaled. If something needs to be scheduled after many tasks have executed,
63 // use base::BarrierClosure.
64 //
65 // On Windows, join processes asynchronously using base::win::ObjectWatcher.
66 //
67 // Where unavoidable, put ScopedAllow* instances in the narrowest scope possible
68 // in the caller making the blocking call but no further down. For example: if a
69 // Cleanup() method needs to do a blocking call, document Cleanup() as blocking
70 // and add a ScopedAllowBlocking instance in callers that can't avoid making
71 // this call from a context where blocking is banned, as such:
72 //
73 //   void Client::MyMethod() {
74 //     (...)
75 //     {
76 //       // Blocking is okay here because XYZ.
77 //       ScopedAllowBlocking allow_blocking;
78 //       my_foo_->Cleanup();
79 //     }
80 //     (...)
81 //   }
82 //
83 //   // This method can block.
84 //   void Foo::Cleanup() {
85 //     // Do NOT add the ScopedAllowBlocking in Cleanup() directly as that hides
86 //     // its blocking nature from unknowing callers and defeats the purpose of
87 //     // these checks.
88 //     FlushStateToDisk();
89 //   }
90 //
91 // Note: In rare situations where the blocking call is an implementation detail
92 // (i.e. the impl makes a call that invokes AssertBlockingAllowed() but it
93 // somehow knows that in practice this will not block), it might be okay to hide
94 // the ScopedAllowBlocking instance in the impl with a comment explaining why
95 // that's okay.
96 
97 class BrowserProcessImpl;
98 class HistogramSynchronizer;
99 class KeyStorageLinux;
100 class NativeBackendKWallet;
101 class NativeDesktopMediaList;
102 class StartupTimeBomb;
103 
104 namespace android_webview {
105 class AwFormDatabaseService;
106 class CookieManager;
107 class ScopedAllowInitGLBindings;
108 class VizCompositorThreadRunnerWebView;
109 }
110 namespace audio {
111 class OutputDevice;
112 }
113 namespace blink {
114 class RTCVideoDecoderAdapter;
115 class RTCVideoEncoder;
116 class SourceStream;
117 class VideoFrameResourceProvider;
118 class WorkerThread;
119 namespace scheduler {
120 class WorkerThread;
121 }
122 }
123 namespace cc {
124 class CompletionEvent;
125 class TileTaskManagerImpl;
126 }
127 namespace chromeos {
128 class BlockingMethodCaller;
129 namespace system {
130 class StatisticsProviderImpl;
131 }
132 }
133 namespace chrome_browser_net {
134 class Predictor;
135 }
136 namespace chrome_cleaner {
137 class SystemReportComponent;
138 }
139 namespace content {
140 class BrowserGpuChannelHostFactory;
141 class BrowserMainLoop;
142 class BrowserProcessSubThread;
143 class BrowserShutdownProfileDumper;
144 class BrowserTestBase;
145 class CategorizedWorkerPool;
146 class DesktopCaptureDevice;
147 class InProcessUtilityThread;
148 class NestedMessagePumpAndroid;
149 class RenderProcessHostImpl;
150 class RenderWidgetHostViewMac;
151 class RTCVideoDecoder;
152 class SandboxHostLinux;
153 class ScopedAllowWaitForDebugURL;
154 class ServiceWorkerContextClient;
155 class SoftwareOutputDeviceMus;
156 class SynchronousCompositor;
157 class SynchronousCompositorHost;
158 class SynchronousCompositorSyncCallBridge;
159 class TextInputClientMac;
160 class WebContentsViewMac;
161 }  // namespace content
162 namespace cronet {
163 class CronetPrefsManager;
164 class CronetURLRequestContext;
165 }  // namespace cronet
166 namespace dbus {
167 class Bus;
168 }
169 namespace disk_cache {
170 class BackendImpl;
171 class InFlightIO;
172 }
173 namespace functions {
174 class ExecScriptScopedAllowBaseSyncPrimitives;
175 }
176 namespace history_report {
177 class HistoryReportJniBridge;
178 }
179 namespace gpu {
180 class GpuChannelHost;
181 }
182 namespace leveldb_env {
183 class DBTracker;
184 }
185 namespace media {
186 class AudioInputDevice;
187 class AudioOutputDevice;
188 class BlockingUrlProtocol;
189 class PaintCanvasVideoRenderer;
190 }
191 namespace memory_instrumentation {
192 class OSMetrics;
193 }
194 namespace midi {
195 class TaskService;  // https://crbug.com/796830
196 }
197 namespace module_installer {
198 class ScopedAllowModulePakLoad;
199 }
200 namespace mojo {
201 class CoreLibraryInitializer;
202 class SyncCallRestrictions;
203 namespace core {
204 class ScopedIPCSupport;
205 }
206 }
207 namespace printing {
208 class PrintJobWorker;
209 class PrinterQuery;
210 }
211 namespace rlz_lib {
212 class FinancialPing;
213 }
214 namespace syncer {
215 class GetLocalChangesRequest;
216 class HttpBridge;
217 class ModelSafeWorker;
218 }
219 namespace ui {
220 class CommandBufferClientImpl;
221 class CommandBufferLocal;
222 class GpuState;
223 class MaterialDesignController;
224 }
225 namespace weblayer {
226 class WebLayerPathProvider;
227 }
228 namespace net {
229 class MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives;
230 class MultiThreadedProxyResolverScopedAllowJoinOnIO;
231 class NetworkChangeNotifierMac;
232 class NetworkConfigWatcherMacThread;
233 namespace internal {
234 class AddressTrackerLinux;
235 }
236 }
237 
238 namespace proxy_resolver {
239 class ScopedAllowThreadJoinForProxyResolverV8Tracing;
240 }
241 
242 namespace remoting {
243 class AutoThread;
244 namespace protocol {
245 class ScopedAllowThreadJoinForWebRtcTransport;
246 }
247 }
248 
249 namespace resource_coordinator {
250 class TabManagerDelegate;
251 }
252 
253 namespace service_manager {
254 class ServiceProcessLauncher;
255 }
256 
257 namespace shell_integration_linux {
258 class LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
259 }
260 
261 namespace ui {
262 class WindowResizeHelperMac;
263 }
264 
265 namespace viz {
266 class HostGpuMemoryBufferManager;
267 }
268 
269 namespace vr {
270 class VrShell;
271 }
272 
273 namespace web {
274 class WebMainLoop;
275 class WebSubThread;
276 }
277 
278 namespace weblayer {
279 class ProfileImpl;
280 }
281 
282 namespace webrtc {
283 class DesktopConfigurationMonitor;
284 }
285 
286 namespace base {
287 
288 namespace sequence_manager {
289 namespace internal {
290 class TaskQueueImpl;
291 }
292 }  // namespace sequence_manager
293 
294 namespace android {
295 class JavaHandlerThread;
296 }
297 
298 namespace internal {
299 class JobTaskSource;
300 class TaskTracker;
301 }
302 
303 class AdjustOOMScoreHelper;
304 class FileDescriptorWatcher;
305 class GetAppOutputScopedAllowBaseSyncPrimitives;
306 class ScopedAllowThreadRecallForStackSamplingProfiler;
307 class SimpleThread;
308 class StackSamplingProfiler;
309 class Thread;
310 
311 #if DCHECK_IS_ON()
312 #define INLINE_IF_DCHECK_IS_OFF BASE_EXPORT
313 #define EMPTY_BODY_IF_DCHECK_IS_OFF
314 #else
315 #define INLINE_IF_DCHECK_IS_OFF inline
316 
317 // The static_assert() eats follow-on semicolons. `= default` would work
318 // too, but it makes clang realize that all the Scoped classes are no-ops in
319 // non-dcheck builds and it starts emitting many -Wunused-variable warnings.
320 #define EMPTY_BODY_IF_DCHECK_IS_OFF \
321   {}                                \
322   static_assert(true, "")
323 #endif
324 
325 namespace internal {
326 
327 // Asserts that blocking calls are allowed in the current scope. This is an
328 // internal call, external code should use ScopedBlockingCall instead, which
329 // serves as a precise annotation of the scope that may/will block.
330 INLINE_IF_DCHECK_IS_OFF void AssertBlockingAllowed()
331     EMPTY_BODY_IF_DCHECK_IS_OFF;
332 
333 }  // namespace internal
334 
335 // Disallows blocking on the current thread.
336 INLINE_IF_DCHECK_IS_OFF void DisallowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
337 
338 // Disallows blocking calls within its scope.
339 class BASE_EXPORT ScopedDisallowBlocking {
340  public:
341   ScopedDisallowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
342   ~ScopedDisallowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
343 
344  private:
345 #if DCHECK_IS_ON()
346   const bool was_disallowed_;
347 #endif
348 
349   DISALLOW_COPY_AND_ASSIGN(ScopedDisallowBlocking);
350 };
351 
352 class BASE_EXPORT ScopedAllowBlocking {
353  private:
354   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest, ScopedAllowBlocking);
355   friend class ScopedAllowBlockingForTesting;
356 
357   // This can only be instantiated by friends. Use ScopedAllowBlockingForTesting
358   // in unit tests to avoid the friend requirement.
359   friend class AdjustOOMScoreHelper;
360   friend class android_webview::ScopedAllowInitGLBindings;
361   friend class content::BrowserProcessSubThread;
362   friend class content::RenderWidgetHostViewMac;  // http://crbug.com/121917
363   friend class content::WebContentsViewMac;
364   friend class cronet::CronetPrefsManager;
365   friend class cronet::CronetURLRequestContext;
366   friend class memory_instrumentation::OSMetrics;
367   friend class module_installer::ScopedAllowModulePakLoad;
368   friend class mojo::CoreLibraryInitializer;
369   friend class printing::PrintJobWorker;
370   friend class resource_coordinator::TabManagerDelegate;  // crbug.com/778703
371   friend class ui::MaterialDesignController;
372   friend class web::WebSubThread;
373   friend class StackSamplingProfiler;
374   friend class weblayer::ProfileImpl;
375   friend class content::RenderProcessHostImpl;
376   friend class weblayer::WebLayerPathProvider;
377 
378   ScopedAllowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
379   ~ScopedAllowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
380 
381 #if DCHECK_IS_ON()
382   const bool was_disallowed_;
383 #endif
384 
385   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBlocking);
386 };
387 
388 class ScopedAllowBlockingForTesting {
389  public:
ScopedAllowBlockingForTesting()390   ScopedAllowBlockingForTesting() {}
~ScopedAllowBlockingForTesting()391   ~ScopedAllowBlockingForTesting() {}
392 
393  private:
394 #if DCHECK_IS_ON()
395   ScopedAllowBlocking scoped_allow_blocking_;
396 #endif
397 
398   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBlockingForTesting);
399 };
400 
401 INLINE_IF_DCHECK_IS_OFF void DisallowBaseSyncPrimitives()
402     EMPTY_BODY_IF_DCHECK_IS_OFF;
403 
404 class BASE_EXPORT ScopedAllowBaseSyncPrimitives {
405  private:
406   // This can only be instantiated by friends. Use
407   // ScopedAllowBaseSyncPrimitivesForTesting in unit tests to avoid the friend
408   // requirement.
409   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
410                            ScopedAllowBaseSyncPrimitives);
411   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
412                            ScopedAllowBaseSyncPrimitivesResetsState);
413   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
414                            ScopedAllowBaseSyncPrimitivesWithBlockingDisallowed);
415 
416   // Allowed usage:
417   friend class SimpleThread;
418   friend class base::GetAppOutputScopedAllowBaseSyncPrimitives;
419   friend class blink::SourceStream;
420   friend class blink::WorkerThread;
421   friend class blink::scheduler::WorkerThread;
422   friend class chrome_cleaner::SystemReportComponent;
423   friend class content::BrowserMainLoop;
424   friend class content::BrowserProcessSubThread;
425   friend class content::ServiceWorkerContextClient;
426   friend class functions::ExecScriptScopedAllowBaseSyncPrimitives;
427   friend class history_report::HistoryReportJniBridge;
428   friend class internal::TaskTracker;
429   friend class leveldb_env::DBTracker;
430   friend class media::BlockingUrlProtocol;
431   friend class mojo::core::ScopedIPCSupport;
432   friend class net::MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives;
433   friend class rlz_lib::FinancialPing;
434   friend class shell_integration_linux::
435       LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
436   friend class syncer::HttpBridge;
437   friend class syncer::GetLocalChangesRequest;
438   friend class syncer::ModelSafeWorker;
439   friend class webrtc::DesktopConfigurationMonitor;
440 
441   // Usage that should be fixed:
442   friend class ::NativeBackendKWallet;            // http://crbug.com/125331
443   friend class ::chromeos::system::
444       StatisticsProviderImpl;                      // http://crbug.com/125385
445   friend class content::TextInputClientMac;        // http://crbug.com/121917
446   friend class blink::VideoFrameResourceProvider;  // http://crbug.com/878070
447 
448   ScopedAllowBaseSyncPrimitives() EMPTY_BODY_IF_DCHECK_IS_OFF;
449   ~ScopedAllowBaseSyncPrimitives() EMPTY_BODY_IF_DCHECK_IS_OFF;
450 
451 #if DCHECK_IS_ON()
452   const bool was_disallowed_;
453 #endif
454 
455   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBaseSyncPrimitives);
456 };
457 
458 class BASE_EXPORT ScopedAllowBaseSyncPrimitivesOutsideBlockingScope {
459  private:
460   // This can only be instantiated by friends. Use
461   // ScopedAllowBaseSyncPrimitivesForTesting in unit tests to avoid the friend
462   // requirement.
463   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
464                            ScopedAllowBaseSyncPrimitivesOutsideBlockingScope);
465   FRIEND_TEST_ALL_PREFIXES(
466       ThreadRestrictionsTest,
467       ScopedAllowBaseSyncPrimitivesOutsideBlockingScopeResetsState);
468 
469   // Allowed usage:
470   friend class ::BrowserProcessImpl;  // http://crbug.com/125207
471   friend class ::KeyStorageLinux;
472   friend class ::NativeDesktopMediaList;
473   friend class ::StartupTimeBomb;
474   friend class android::JavaHandlerThread;
475   friend class android_webview::
476       AwFormDatabaseService;  // http://crbug.com/904431
477   friend class android_webview::CookieManager;
478   friend class android_webview::VizCompositorThreadRunnerWebView;
479   friend class audio::OutputDevice;
480   friend class base::sequence_manager::internal::TaskQueueImpl;
481   friend class base::FileDescriptorWatcher;
482   friend class base::internal::JobTaskSource;
483   friend class base::ScopedAllowThreadRecallForStackSamplingProfiler;
484   friend class base::StackSamplingProfiler;
485   friend class blink::RTCVideoDecoderAdapter;
486   friend class blink::RTCVideoEncoder;
487   friend class cc::TileTaskManagerImpl;
488   friend class content::CategorizedWorkerPool;
489   friend class content::DesktopCaptureDevice;
490   friend class content::InProcessUtilityThread;
491   friend class content::RTCVideoDecoder;
492   friend class content::SandboxHostLinux;
493   friend class content::ScopedAllowWaitForDebugURL;
494   friend class content::SynchronousCompositor;
495   friend class content::SynchronousCompositorHost;
496   friend class content::SynchronousCompositorSyncCallBridge;
497   friend class media::AudioInputDevice;
498   friend class media::AudioOutputDevice;
499   friend class media::PaintCanvasVideoRenderer;
500   friend class mojo::SyncCallRestrictions;
501   friend class net::NetworkConfigWatcherMacThread;
502   friend class viz::HostGpuMemoryBufferManager;
503   friend class vr::VrShell;
504 
505   // Usage that should be fixed:
506   friend class ::chromeos::BlockingMethodCaller;  // http://crbug.com/125360
507   friend class base::Thread;                      // http://crbug.com/918039
508   friend class cc::CompletionEvent;               // http://crbug.com/902653
509   friend class content::
510       BrowserGpuChannelHostFactory;                 // http://crbug.com/125248
511   friend class dbus::Bus;                           // http://crbug.com/125222
512   friend class disk_cache::BackendImpl;             // http://crbug.com/74623
513   friend class disk_cache::InFlightIO;              // http://crbug.com/74623
514   friend class gpu::GpuChannelHost;                 // http://crbug.com/125264
515   friend class remoting::protocol::
516       ScopedAllowThreadJoinForWebRtcTransport;      // http://crbug.com/660081
517   friend class midi::TaskService;                   // https://crbug.com/796830
518   friend class net::internal::AddressTrackerLinux;  // http://crbug.com/125097
519   friend class net::
520       MultiThreadedProxyResolverScopedAllowJoinOnIO;  // http://crbug.com/69710
521   friend class net::NetworkChangeNotifierMac;         // http://crbug.com/125097
522   friend class printing::PrinterQuery;                 // http://crbug.com/66082
523   friend class proxy_resolver::
524       ScopedAllowThreadJoinForProxyResolverV8Tracing;  // http://crbug.com/69710
525   friend class remoting::AutoThread;  // https://crbug.com/944316
526   // Not used in production yet, https://crbug.com/844078.
527   friend class service_manager::ServiceProcessLauncher;
528   friend class ui::WindowResizeHelperMac;  // http://crbug.com/902829
529 
530   ScopedAllowBaseSyncPrimitivesOutsideBlockingScope()
531       EMPTY_BODY_IF_DCHECK_IS_OFF;
532   ~ScopedAllowBaseSyncPrimitivesOutsideBlockingScope()
533       EMPTY_BODY_IF_DCHECK_IS_OFF;
534 
535 #if DCHECK_IS_ON()
536   const bool was_disallowed_;
537 #endif
538 
539   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBaseSyncPrimitivesOutsideBlockingScope);
540 };
541 
542 class BASE_EXPORT ScopedAllowBaseSyncPrimitivesForTesting {
543  public:
544   ScopedAllowBaseSyncPrimitivesForTesting() EMPTY_BODY_IF_DCHECK_IS_OFF;
545   ~ScopedAllowBaseSyncPrimitivesForTesting() EMPTY_BODY_IF_DCHECK_IS_OFF;
546 
547  private:
548 #if DCHECK_IS_ON()
549   const bool was_disallowed_;
550 #endif
551 
552   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBaseSyncPrimitivesForTesting);
553 };
554 
555 // Counterpart to base::DisallowUnresponsiveTasks() for tests to allow them to
556 // block their thread after it was banned.
557 class BASE_EXPORT ScopedAllowUnresponsiveTasksForTesting {
558  public:
559   ScopedAllowUnresponsiveTasksForTesting() EMPTY_BODY_IF_DCHECK_IS_OFF;
560   ~ScopedAllowUnresponsiveTasksForTesting() EMPTY_BODY_IF_DCHECK_IS_OFF;
561 
562  private:
563 #if DCHECK_IS_ON()
564   const bool was_disallowed_base_sync_;
565   const bool was_disallowed_blocking_;
566   const bool was_disallowed_cpu_;
567 #endif
568 
569   DISALLOW_COPY_AND_ASSIGN(ScopedAllowUnresponsiveTasksForTesting);
570 };
571 
572 namespace internal {
573 
574 // Asserts that waiting on a //base sync primitive is allowed in the current
575 // scope.
576 INLINE_IF_DCHECK_IS_OFF void AssertBaseSyncPrimitivesAllowed()
577     EMPTY_BODY_IF_DCHECK_IS_OFF;
578 
579 // Resets all thread restrictions on the current thread.
580 INLINE_IF_DCHECK_IS_OFF void ResetThreadRestrictionsForTesting()
581     EMPTY_BODY_IF_DCHECK_IS_OFF;
582 
583 }  // namespace internal
584 
585 // Asserts that running long CPU work is allowed in the current scope.
586 INLINE_IF_DCHECK_IS_OFF void AssertLongCPUWorkAllowed()
587     EMPTY_BODY_IF_DCHECK_IS_OFF;
588 
589 INLINE_IF_DCHECK_IS_OFF void DisallowUnresponsiveTasks()
590     EMPTY_BODY_IF_DCHECK_IS_OFF;
591 
592 class BASE_EXPORT ThreadRestrictions {
593  public:
594   // Constructing a ScopedAllowIO temporarily allows IO for the current
595   // thread.  Doing this is almost certainly always incorrect.
596   //
597   // DEPRECATED. Use ScopedAllowBlocking(ForTesting).
598   class BASE_EXPORT ScopedAllowIO {
599    public:
600     ScopedAllowIO() EMPTY_BODY_IF_DCHECK_IS_OFF;
601     ~ScopedAllowIO() EMPTY_BODY_IF_DCHECK_IS_OFF;
602 
603    private:
604 #if DCHECK_IS_ON()
605     const bool was_allowed_;
606 #endif
607 
608     DISALLOW_COPY_AND_ASSIGN(ScopedAllowIO);
609   };
610 
611 #if DCHECK_IS_ON()
612   // Set whether the current thread to make IO calls.
613   // Threads start out in the *allowed* state.
614   // Returns the previous value.
615   //
616   // DEPRECATED. Use ScopedAllowBlocking(ForTesting) or ScopedDisallowBlocking.
617   static bool SetIOAllowed(bool allowed);
618 
619   // Set whether the current thread can use singletons.  Returns the previous
620   // value.
621   static bool SetSingletonAllowed(bool allowed);
622 
623   // Check whether the current thread is allowed to use singletons (Singleton /
624   // LazyInstance).  DCHECKs if not.
625   static void AssertSingletonAllowed();
626 
627   // Disable waiting on the current thread. Threads start out in the *allowed*
628   // state. Returns the previous value.
629   //
630   // DEPRECATED. Use DisallowBaseSyncPrimitives.
631   static void DisallowWaiting();
632 #else
633   // Inline the empty definitions of these functions so that they can be
634   // compiled out.
SetIOAllowed(bool allowed)635   static bool SetIOAllowed(bool allowed) { return true; }
SetSingletonAllowed(bool allowed)636   static bool SetSingletonAllowed(bool allowed) { return true; }
AssertSingletonAllowed()637   static void AssertSingletonAllowed() {}
DisallowWaiting()638   static void DisallowWaiting() {}
639 #endif
640 
641  private:
642   // DO NOT ADD ANY OTHER FRIEND STATEMENTS.
643   // BEGIN ALLOWED USAGE.
644   friend class content::BrowserMainLoop;
645   friend class content::BrowserShutdownProfileDumper;
646   friend class content::BrowserTestBase;
647   friend class content::ScopedAllowWaitForDebugURL;
648   friend class ::HistogramSynchronizer;
649   friend class internal::TaskTracker;
650   friend class web::WebMainLoop;
651   friend class MessagePumpDefault;
652   friend class PlatformThread;
653   friend class ui::CommandBufferClientImpl;
654   friend class ui::CommandBufferLocal;
655   friend class ui::GpuState;
656 
657   // END ALLOWED USAGE.
658   // BEGIN USAGE THAT NEEDS TO BE FIXED.
659   friend class chrome_browser_net::Predictor;     // http://crbug.com/78451
660 #if !defined(OFFICIAL_BUILD)
661   friend class content::SoftwareOutputDeviceMus;  // Interim non-production code
662 #endif
663 // END USAGE THAT NEEDS TO BE FIXED.
664 
665 #if DCHECK_IS_ON()
666   // DEPRECATED. Use ScopedAllowBaseSyncPrimitives.
667   static bool SetWaitAllowed(bool allowed);
668 #else
SetWaitAllowed(bool allowed)669   static bool SetWaitAllowed(bool allowed) { return true; }
670 #endif
671 
672   DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions);
673 };
674 
675 #undef INLINE_IF_DCHECK_IS_OFF
676 #undef EMPTY_BODY_IF_DCHECK_IS_OFF
677 
678 }  // namespace base
679 
680 #endif  // BASE_THREADING_THREAD_RESTRICTIONS_H_
681