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