thread_restrictions.h revision ddb351dbec246cf1fab5ec20d2d5520909041de1
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
11namespace 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
39class 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:
45    ScopedAllowIO() { previous_value_ = SetIOAllowed(true); }
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:
58    ScopedAllowSingleton() { previous_value_ = SetSingletonAllowed(true); }
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.
89  static bool SetIOAllowed(bool allowed) { return true; }
90  static void AssertIOAllowed() {}
91  static bool SetSingletonAllowed(bool allowed) { return true; }
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