• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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