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