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 #include "base/threading/thread_restrictions.h"
6 
7 #if ENABLE_THREAD_RESTRICTIONS
8 
9 #include "base/lazy_instance.h"
10 #include "base/logging.h"
11 #include "base/threading/thread_local.h"
12 
13 namespace base {
14 
15 namespace {
16 
17 LazyInstance<ThreadLocalBoolean>::Leaky
18     g_io_disallowed = LAZY_INSTANCE_INITIALIZER;
19 
20 LazyInstance<ThreadLocalBoolean>::Leaky
21     g_singleton_disallowed = LAZY_INSTANCE_INITIALIZER;
22 
23 LazyInstance<ThreadLocalBoolean>::Leaky
24     g_wait_disallowed = LAZY_INSTANCE_INITIALIZER;
25 
26 }  // namespace
27 
28 // static
SetIOAllowed(bool allowed)29 bool ThreadRestrictions::SetIOAllowed(bool allowed) {
30   bool previous_disallowed = g_io_disallowed.Get().Get();
31   g_io_disallowed.Get().Set(!allowed);
32   return !previous_disallowed;
33 }
34 
35 // static
AssertIOAllowed()36 void ThreadRestrictions::AssertIOAllowed() {
37   if (g_io_disallowed.Get().Get()) {
38     LOG(FATAL) <<
39         "Function marked as IO-only was called from a thread that "
40         "disallows IO!  If this thread really should be allowed to "
41         "make IO calls, adjust the call to "
42         "base::ThreadRestrictions::SetIOAllowed() in this thread's "
43         "startup.";
44   }
45 }
46 
47 // static
SetSingletonAllowed(bool allowed)48 bool ThreadRestrictions::SetSingletonAllowed(bool allowed) {
49   bool previous_disallowed = g_singleton_disallowed.Get().Get();
50   g_singleton_disallowed.Get().Set(!allowed);
51   return !previous_disallowed;
52 }
53 
54 // static
AssertSingletonAllowed()55 void ThreadRestrictions::AssertSingletonAllowed() {
56   if (g_singleton_disallowed.Get().Get()) {
57     LOG(FATAL) << "LazyInstance/Singleton is not allowed to be used on this "
58                << "thread.  Most likely it's because this thread is not "
59                << "joinable, so AtExitManager may have deleted the object "
60                << "on shutdown, leading to a potential shutdown crash.";
61   }
62 }
63 
64 // static
DisallowWaiting()65 void ThreadRestrictions::DisallowWaiting() {
66   g_wait_disallowed.Get().Set(true);
67 }
68 
69 // static
AssertWaitAllowed()70 void ThreadRestrictions::AssertWaitAllowed() {
71   if (g_wait_disallowed.Get().Get()) {
72     LOG(FATAL) << "Waiting is not allowed to be used on this thread to prevent "
73                << "jank and deadlock.";
74   }
75 }
76 
SetWaitAllowed(bool allowed)77 bool ThreadRestrictions::SetWaitAllowed(bool allowed) {
78   bool previous_disallowed = g_wait_disallowed.Get().Get();
79   g_wait_disallowed.Get().Set(!allowed);
80   return !previous_disallowed;
81 }
82 
83 }  // namespace base
84 
85 #endif  // ENABLE_THREAD_RESTRICTIONS
86