michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "base/threading/thread_restrictions.h" michael@0: michael@0: #if ENABLE_THREAD_RESTRICTIONS michael@0: michael@0: #include "base/lazy_instance.h" michael@0: #include "base/logging.h" michael@0: #include "base/threading/thread_local.h" michael@0: michael@0: namespace base { michael@0: michael@0: namespace { michael@0: michael@0: LazyInstance::Leaky michael@0: g_io_disallowed = LAZY_INSTANCE_INITIALIZER; michael@0: michael@0: LazyInstance::Leaky michael@0: g_singleton_disallowed = LAZY_INSTANCE_INITIALIZER; michael@0: michael@0: LazyInstance::Leaky michael@0: g_wait_disallowed = LAZY_INSTANCE_INITIALIZER; michael@0: michael@0: } // anonymous namespace michael@0: michael@0: // static michael@0: bool ThreadRestrictions::SetIOAllowed(bool allowed) { michael@0: bool previous_disallowed = g_io_disallowed.Get().Get(); michael@0: g_io_disallowed.Get().Set(!allowed); michael@0: return !previous_disallowed; michael@0: } michael@0: michael@0: // static michael@0: void ThreadRestrictions::AssertIOAllowed() { michael@0: if (g_io_disallowed.Get().Get()) { michael@0: LOG(FATAL) << michael@0: "Function marked as IO-only was called from a thread that " michael@0: "disallows IO! If this thread really should be allowed to " michael@0: "make IO calls, adjust the call to " michael@0: "base::ThreadRestrictions::SetIOAllowed() in this thread's " michael@0: "startup."; michael@0: } michael@0: } michael@0: michael@0: // static michael@0: bool ThreadRestrictions::SetSingletonAllowed(bool allowed) { michael@0: bool previous_disallowed = g_singleton_disallowed.Get().Get(); michael@0: g_singleton_disallowed.Get().Set(!allowed); michael@0: return !previous_disallowed; michael@0: } michael@0: michael@0: // static michael@0: void ThreadRestrictions::AssertSingletonAllowed() { michael@0: if (g_singleton_disallowed.Get().Get()) { michael@0: LOG(FATAL) << "LazyInstance/Singleton is not allowed to be used on this " michael@0: << "thread. Most likely it's because this thread is not " michael@0: << "joinable, so AtExitManager may have deleted the object " michael@0: << "on shutdown, leading to a potential shutdown crash."; michael@0: } michael@0: } michael@0: michael@0: // static michael@0: void ThreadRestrictions::DisallowWaiting() { michael@0: g_wait_disallowed.Get().Set(true); michael@0: } michael@0: michael@0: // static michael@0: void ThreadRestrictions::AssertWaitAllowed() { michael@0: if (g_wait_disallowed.Get().Get()) { michael@0: LOG(FATAL) << "Waiting is not allowed to be used on this thread to prevent" michael@0: << "jank and deadlock."; michael@0: } michael@0: } michael@0: michael@0: bool ThreadRestrictions::SetWaitAllowed(bool allowed) { michael@0: bool previous_disallowed = g_wait_disallowed.Get().Get(); michael@0: g_wait_disallowed.Get().Set(!allowed); michael@0: return !previous_disallowed; michael@0: } michael@0: michael@0: } // namespace base michael@0: michael@0: #endif // ENABLE_THREAD_RESTRICTIONS