// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_THREAD_RESTRICTIONS_H_ #define BASE_THREAD_RESTRICTIONS_H_ #include "base/basictypes.h" namespace base { // Certain behavior is disallowed on certain threads. ThreadRestrictions helps // enforce these rules. Examples of such rules: // // * Do not do blocking IO (makes the thread janky) // * Do not access Singleton/LazyInstance (may lead to shutdown crashes) // // Here's more about how the protection works: // // 1) If a thread should not be allowed to make IO calls, mark it: // base::ThreadRestrictions::SetIOAllowed(false); // By default, threads *are* allowed to make IO calls. // In Chrome browser code, IO calls should be proxied to the File thread. // // 2) If a function makes a call that will go out to disk, check whether the // current thread is allowed: // base::ThreadRestrictions::AssertIOAllowed(); // // ThreadRestrictions does nothing in release builds; it is debug-only. // // Style tip: where should you put AssertIOAllowed checks? It's best // if you put them as close to the disk access as possible, at the // lowest level. This rule is simple to follow and helps catch all // callers. For example, if your function GoDoSomeBlockingDiskCall() // only calls other functions in Chrome and not fopen(), you should go // add the AssertIOAllowed checks in the helper functions. class ThreadRestrictions { public: // Constructing a ScopedAllowIO temporarily allows IO for the current // thread. Doing this is almost certainly always incorrect. class ScopedAllowIO { public: ScopedAllowIO() { previous_value_ = SetIOAllowed(true); } ~ScopedAllowIO() { SetIOAllowed(previous_value_); } private: // Whether IO is allowed when the ScopedAllowIO was constructed. bool previous_value_; DISALLOW_COPY_AND_ASSIGN(ScopedAllowIO); }; // Constructing a ScopedAllowSingleton temporarily allows accessing for the // current thread. Doing this is almost always incorrect. class ScopedAllowSingleton { public: ScopedAllowSingleton() { previous_value_ = SetSingletonAllowed(true); } ~ScopedAllowSingleton() { SetSingletonAllowed(previous_value_); } private: // Whether singleton use is allowed when the ScopedAllowSingleton was // constructed. bool previous_value_; DISALLOW_COPY_AND_ASSIGN(ScopedAllowSingleton); }; #ifndef NDEBUG // Set whether the current thread to make IO calls. // Threads start out in the *allowed* state. // Returns the previous value. static bool SetIOAllowed(bool allowed); // Check whether the current thread is allowed to make IO calls, // and DCHECK if not. See the block comment above the class for // a discussion of where to add these checks. static void AssertIOAllowed(); // Set whether the current thread can use singletons. Returns the previous // value. static bool SetSingletonAllowed(bool allowed); // Check whether the current thread is allowed to use singletons (Singleton / // LazyInstance). DCHECKs if not. static void AssertSingletonAllowed(); #else // In Release builds, inline the empty definitions of these functions so // that they can be compiled out. static bool SetIOAllowed(bool allowed) { return true; } static void AssertIOAllowed() {} static bool SetSingletonAllowed(bool allowed) { return true; } static void AssertSingletonAllowed() {} #endif private: DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions); }; } // namespace base #endif // BASE_THREAD_RESTRICTIONS_H_