tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

thread_checker.h (5740B)


      1 // Copyright 2012 The Chromium Authors
      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_CHECKER_H_
      6 #define BASE_THREADING_THREAD_CHECKER_H_
      7 
      8 #include "base/base_export.h"
      9 #include "base/dcheck_is_on.h"
     10 #include "base/macros/uniquify.h"
     11 #include "base/strings/string_piece.h"
     12 #include "base/thread_annotations.h"
     13 #include "base/threading/thread_checker_impl.h"
     14 
     15 // ThreadChecker is a helper class used to help verify that some methods of a
     16 // class are called from the same thread (for thread-affinity).  It supports
     17 // thread safety annotations (see base/thread_annotations.h).
     18 //
     19 // Use the macros below instead of the ThreadChecker directly so that the unused
     20 // member doesn't result in an extra byte (four when padded) per instance in
     21 // production.
     22 //
     23 // Usage of this class should be *rare* as most classes require thread-safety
     24 // but not thread-affinity. Prefer base::SequenceChecker to verify thread-safe
     25 // access.
     26 //
     27 // Thread-affinity checks should only be required in classes that use thread-
     28 // local-storage or a third-party API that does.
     29 //
     30 // Prefer to encode the minimum requirements of each class instead of the
     31 // environment it happens to run in today. e.g. if a class requires thread-
     32 // safety but not thread-affinity, use a SequenceChecker even if it happens to
     33 // run on a SingleThreadTaskRunner today. That makes it easier to understand
     34 // what would need to change to turn that SingleThreadTaskRunner into a
     35 // SequencedTaskRunner for ease of scheduling as well as minimizes side-effects
     36 // if that change is made.
     37 //
     38 // Debugging:
     39 //   If ThreadChecker::EnableStackLogging() is called beforehand, then when
     40 //   ThreadChecker fails, in addition to crashing with a stack trace of where
     41 //   the violation occurred, it will also dump a stack trace of where the
     42 //   checker was bound to a thread.
     43 //
     44 // Usage:
     45 //   class MyClass {
     46 //    public:
     47 //     MyClass() {
     48 //       // It's sometimes useful to detach on construction for objects that are
     49 //       // constructed in one place and forever after used from another
     50 //       // thread.
     51 //       DETACH_FROM_THREAD(thread_checker_);
     52 //     }
     53 //
     54 //     ~MyClass() {
     55 //       // ThreadChecker doesn't automatically check it's destroyed on origin
     56 //       // thread for the same reason it's sometimes detached in the
     57 //       // constructor. It's okay to destroy off thread if the owner otherwise
     58 //       // knows usage on the associated thread is done. If you're not
     59 //       // detaching in the constructor, you probably want to explicitly check
     60 //       // in the destructor.
     61 //       DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
     62 //     }
     63 //
     64 //     void MyMethod() {
     65 //       DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
     66 //       ... (do stuff) ...
     67 //     }
     68 //
     69 //     void MyOtherMethod()
     70 //         VALID_CONTEXT_REQUIRED(thread_checker_) {
     71 //       foo_ = 42;
     72 //     }
     73 //
     74 //    private:
     75 //     int foo_ GUARDED_BY_CONTEXT(thread_checker_);
     76 //
     77 //     THREAD_CHECKER(thread_checker_);
     78 //   }
     79 
     80 #if DCHECK_IS_ON()
     81 #define THREAD_CHECKER(name) base::ThreadChecker name
     82 #define DCHECK_CALLED_ON_VALID_THREAD(name, ...)   \
     83  base::ScopedValidateThreadChecker BASE_UNIQUIFY( \
     84      scoped_validate_thread_checker_)(name, ##__VA_ARGS__);
     85 #define DETACH_FROM_THREAD(name) (name).DetachFromThread()
     86 #else  // DCHECK_IS_ON()
     87 #define THREAD_CHECKER(name) static_assert(true, "")
     88 #define DCHECK_CALLED_ON_VALID_THREAD(name, ...) EAT_CHECK_STREAM_PARAMS()
     89 #define DETACH_FROM_THREAD(name)
     90 #endif  // DCHECK_IS_ON()
     91 
     92 namespace base {
     93 
     94 // Do nothing implementation, for use in release mode.
     95 //
     96 // Note: You should almost always use the ThreadChecker class (through the above
     97 // macros) to get the right version for your build configuration.
     98 // Note: This is only a check, not a "lock". It is marked "LOCKABLE" only in
     99 // order to support thread_annotations.h.
    100 class LOCKABLE ThreadCheckerDoNothing {
    101 public:
    102  static void EnableStackLogging() {}
    103 
    104  ThreadCheckerDoNothing() = default;
    105 
    106  ThreadCheckerDoNothing(const ThreadCheckerDoNothing&) = delete;
    107  ThreadCheckerDoNothing& operator=(const ThreadCheckerDoNothing&) = delete;
    108 
    109  // Moving between matching threads is allowed to help classes with
    110  // ThreadCheckers that want a default move-construct/assign.
    111  ThreadCheckerDoNothing(ThreadCheckerDoNothing&& other) = default;
    112  ThreadCheckerDoNothing& operator=(ThreadCheckerDoNothing&& other) = default;
    113 
    114  [[nodiscard]] bool CalledOnValidThread(
    115      std::unique_ptr<void*> = nullptr) const {
    116    return true;
    117  }
    118  void DetachFromThread() {}
    119 };
    120 
    121 // Note that ThreadCheckerImpl::CalledOnValidThread() returns false when called
    122 // from tasks posted to SingleThreadTaskRunners bound to different sequences,
    123 // even if the tasks happen to run on the same thread (e.g. two independent
    124 // SingleThreadTaskRunners on the ThreadPool that happen to share a thread).
    125 #if DCHECK_IS_ON()
    126 class ThreadChecker : public ThreadCheckerImpl {
    127 };
    128 #else
    129 class ThreadChecker : public ThreadCheckerDoNothing {
    130 };
    131 #endif  // DCHECK_IS_ON()
    132 
    133 #if DCHECK_IS_ON()
    134 class BASE_EXPORT SCOPED_LOCKABLE ScopedValidateThreadChecker {
    135 public:
    136  explicit ScopedValidateThreadChecker(const ThreadChecker& checker)
    137      EXCLUSIVE_LOCK_FUNCTION(checker);
    138  ScopedValidateThreadChecker(const ThreadChecker& checker,
    139                              const StringPiece& msg)
    140      EXCLUSIVE_LOCK_FUNCTION(checker);
    141 
    142  ScopedValidateThreadChecker(const ScopedValidateThreadChecker&) = delete;
    143  ScopedValidateThreadChecker& operator=(const ScopedValidateThreadChecker&) =
    144      delete;
    145 
    146  ~ScopedValidateThreadChecker() UNLOCK_FUNCTION();
    147 };
    148 #endif
    149 
    150 }  // namespace base
    151 
    152 #endif  // BASE_THREADING_THREAD_CHECKER_H_