Home | History | Annotate | Download | only in threading
      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:
     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