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
13namespace base {
14
15namespace {
16
17LazyInstance<ThreadLocalBoolean>::Leaky
18    g_io_disallowed = LAZY_INSTANCE_INITIALIZER;
19
20LazyInstance<ThreadLocalBoolean>::Leaky
21    g_singleton_disallowed = LAZY_INSTANCE_INITIALIZER;
22
23LazyInstance<ThreadLocalBoolean>::Leaky
24    g_wait_disallowed = LAZY_INSTANCE_INITIALIZER;
25
26}  // anonymous namespace
27
28// static
29bool 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
36void 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
48bool 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
55void 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
65void ThreadRestrictions::DisallowWaiting() {
66  g_wait_disallowed.Get().Set(true);
67}
68
69// static
70void 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
77bool 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