1 // Copyright (c) 2011 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_api.h" 9 #include "base/basictypes.h" 10 11 namespace base { 12 13 // Certain behavior is disallowed on certain threads. ThreadRestrictions helps 14 // enforce these rules. Examples of such rules: 15 // 16 // * Do not do blocking IO (makes the thread janky) 17 // * Do not access Singleton/LazyInstance (may lead to shutdown crashes) 18 // 19 // Here's more about how the protection works: 20 // 21 // 1) If a thread should not be allowed to make IO calls, mark it: 22 // base::ThreadRestrictions::SetIOAllowed(false); 23 // By default, threads *are* allowed to make IO calls. 24 // In Chrome browser code, IO calls should be proxied to the File thread. 25 // 26 // 2) If a function makes a call that will go out to disk, check whether the 27 // current thread is allowed: 28 // base::ThreadRestrictions::AssertIOAllowed(); 29 // 30 // ThreadRestrictions does nothing in release builds; it is debug-only. 31 // 32 // Style tip: where should you put AssertIOAllowed checks? It's best 33 // if you put them as close to the disk access as possible, at the 34 // lowest level. This rule is simple to follow and helps catch all 35 // callers. For example, if your function GoDoSomeBlockingDiskCall() 36 // only calls other functions in Chrome and not fopen(), you should go 37 // add the AssertIOAllowed checks in the helper functions. 38 39 class BASE_API ThreadRestrictions { 40 public: 41 // Constructing a ScopedAllowIO temporarily allows IO for the current 42 // thread. Doing this is almost certainly always incorrect. 43 class BASE_API ScopedAllowIO { 44 public: ScopedAllowIO()45 ScopedAllowIO() { previous_value_ = SetIOAllowed(true); } ~ScopedAllowIO()46 ~ScopedAllowIO() { SetIOAllowed(previous_value_); } 47 private: 48 // Whether IO is allowed when the ScopedAllowIO was constructed. 49 bool previous_value_; 50 51 DISALLOW_COPY_AND_ASSIGN(ScopedAllowIO); 52 }; 53 54 // Constructing a ScopedAllowSingleton temporarily allows accessing for the 55 // current thread. Doing this is almost always incorrect. 56 class BASE_API ScopedAllowSingleton { 57 public: ScopedAllowSingleton()58 ScopedAllowSingleton() { previous_value_ = SetSingletonAllowed(true); } ~ScopedAllowSingleton()59 ~ScopedAllowSingleton() { SetSingletonAllowed(previous_value_); } 60 private: 61 // Whether singleton use is allowed when the ScopedAllowSingleton was 62 // constructed. 63 bool previous_value_; 64 65 DISALLOW_COPY_AND_ASSIGN(ScopedAllowSingleton); 66 }; 67 68 #ifndef NDEBUG 69 // Set whether the current thread to make IO calls. 70 // Threads start out in the *allowed* state. 71 // Returns the previous value. 72 static bool SetIOAllowed(bool allowed); 73 74 // Check whether the current thread is allowed to make IO calls, 75 // and DCHECK if not. See the block comment above the class for 76 // a discussion of where to add these checks. 77 static void AssertIOAllowed(); 78 79 // Set whether the current thread can use singletons. Returns the previous 80 // value. 81 static bool SetSingletonAllowed(bool allowed); 82 83 // Check whether the current thread is allowed to use singletons (Singleton / 84 // LazyInstance). DCHECKs if not. 85 static void AssertSingletonAllowed(); 86 #else 87 // In Release builds, inline the empty definitions of these functions so 88 // that they can be compiled out. SetIOAllowed(bool allowed)89 static bool SetIOAllowed(bool allowed) { return true; } AssertIOAllowed()90 static void AssertIOAllowed() {} SetSingletonAllowed(bool allowed)91 static bool SetSingletonAllowed(bool allowed) { return true; } AssertSingletonAllowed()92 static void AssertSingletonAllowed() {} 93 #endif 94 95 private: 96 DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions); 97 }; 98 99 } // namespace base 100 101 #endif // BASE_THREADING_THREAD_RESTRICTIONS_H_ 102