1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Use of this source code is governed by a BSD-style license that can be 3731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// found in the LICENSE file. 4731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 53f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#ifndef BASE_THREADING_THREAD_RESTRICTIONS_H_ 63f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#define BASE_THREADING_THREAD_RESTRICTIONS_H_ 7731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/base_api.h" 9513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/basictypes.h" 10513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 11731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace base { 12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 13201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Certain behavior is disallowed on certain threads. ThreadRestrictions helps 14201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// enforce these rules. Examples of such rules: 15201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// 16201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// * Do not do blocking IO (makes the thread janky) 17201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// * Do not access Singleton/LazyInstance (may lead to shutdown crashes) 18201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// 19201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Here's more about how the protection works: 20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// 21731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// 1) If a thread should not be allowed to make IO calls, mark it: 22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// base::ThreadRestrictions::SetIOAllowed(false); 23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// By default, threads *are* allowed to make IO calls. 24731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// In Chrome browser code, IO calls should be proxied to the File thread. 25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// 26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// 2) If a function makes a call that will go out to disk, check whether the 27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// current thread is allowed: 28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// base::ThreadRestrictions::AssertIOAllowed(); 29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// 30731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// ThreadRestrictions does nothing in release builds; it is debug-only. 31731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// 32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Style tip: where should you put AssertIOAllowed checks? It's best 33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// if you put them as close to the disk access as possible, at the 34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// lowest level. This rule is simple to follow and helps catch all 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// callers. For example, if your function GoDoSomeBlockingDiskCall() 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// only calls other functions in Chrome and not fopen(), you should go 37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// add the AssertIOAllowed checks in the helper functions. 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass BASE_API ThreadRestrictions { 40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick public: 41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Constructing a ScopedAllowIO temporarily allows IO for the current 42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // thread. Doing this is almost certainly always incorrect. 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen class BASE_API ScopedAllowIO { 44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch public: 45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ScopedAllowIO() { previous_value_ = SetIOAllowed(true); } 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ~ScopedAllowIO() { SetIOAllowed(previous_value_); } 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch private: 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Whether IO is allowed when the ScopedAllowIO was constructed. 49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool previous_value_; 50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DISALLOW_COPY_AND_ASSIGN(ScopedAllowIO); 52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch }; 53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 54201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Constructing a ScopedAllowSingleton temporarily allows accessing for the 55201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // current thread. Doing this is almost always incorrect. 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen class BASE_API ScopedAllowSingleton { 57201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch public: 58201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ScopedAllowSingleton() { previous_value_ = SetSingletonAllowed(true); } 59201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ~ScopedAllowSingleton() { SetSingletonAllowed(previous_value_); } 60201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch private: 61201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Whether singleton use is allowed when the ScopedAllowSingleton was 62201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // constructed. 63201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch bool previous_value_; 64201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 65201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DISALLOW_COPY_AND_ASSIGN(ScopedAllowSingleton); 66201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch }; 67201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#ifndef NDEBUG 69731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Set whether the current thread to make IO calls. 70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Threads start out in the *allowed* state. 71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Returns the previous value. 72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch static bool SetIOAllowed(bool allowed); 73731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 74731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Check whether the current thread is allowed to make IO calls, 75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // and DCHECK if not. See the block comment above the class for 76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // a discussion of where to add these checks. 77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick static void AssertIOAllowed(); 78201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 79201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Set whether the current thread can use singletons. Returns the previous 80201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // value. 81201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch static bool SetSingletonAllowed(bool allowed); 82201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 83201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Check whether the current thread is allowed to use singletons (Singleton / 84201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // LazyInstance). DCHECKs if not. 85201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch static void AssertSingletonAllowed(); 86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#else 87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // In Release builds, inline the empty definitions of these functions so 88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // that they can be compiled out. 89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch static bool SetIOAllowed(bool allowed) { return true; } 90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch static void AssertIOAllowed() {} 91201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch static bool SetSingletonAllowed(bool allowed) { return true; } 92201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch static void AssertSingletonAllowed() {} 93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif 94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick private: 96201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions); 97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}; 98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} // namespace base 100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#endif // BASE_THREADING_THREAD_RESTRICTIONS_H_ 102