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: EnableStackLogging()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 } DetachFromThread()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_ 153