xref: /aosp_15_r20/external/libchrome/base/threading/thread_checker.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #ifndef BASE_THREADING_THREAD_CHECKER_H_
6*635a8641SAndroid Build Coastguard Worker #define BASE_THREADING_THREAD_CHECKER_H_
7*635a8641SAndroid Build Coastguard Worker 
8*635a8641SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
9*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
10*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_checker_impl.h"
11*635a8641SAndroid Build Coastguard Worker 
12*635a8641SAndroid Build Coastguard Worker // ThreadChecker is a helper class used to help verify that some methods of a
13*635a8641SAndroid Build Coastguard Worker // class are called from the same thread (for thread-affinity).
14*635a8641SAndroid Build Coastguard Worker //
15*635a8641SAndroid Build Coastguard Worker // Use the macros below instead of the ThreadChecker directly so that the unused
16*635a8641SAndroid Build Coastguard Worker // member doesn't result in an extra byte (four when padded) per instance in
17*635a8641SAndroid Build Coastguard Worker // production.
18*635a8641SAndroid Build Coastguard Worker //
19*635a8641SAndroid Build Coastguard Worker // Usage of this class should be *rare* as most classes require thread-safety
20*635a8641SAndroid Build Coastguard Worker // but not thread-affinity. Prefer base::SequenceChecker to verify thread-safe
21*635a8641SAndroid Build Coastguard Worker // access.
22*635a8641SAndroid Build Coastguard Worker //
23*635a8641SAndroid Build Coastguard Worker // Thread-affinity checks should only be required in classes that use thread-
24*635a8641SAndroid Build Coastguard Worker // local-storage or a third-party API that does.
25*635a8641SAndroid Build Coastguard Worker //
26*635a8641SAndroid Build Coastguard Worker // Prefer to encode the minimum requirements of each class instead of the
27*635a8641SAndroid Build Coastguard Worker // environment it happens to run in today. e.g. if a class requires thread-
28*635a8641SAndroid Build Coastguard Worker // safety but not thread-affinity, use a SequenceChecker even if it happens to
29*635a8641SAndroid Build Coastguard Worker // run on a SingleThreadTaskRunner today. That makes it easier to understand
30*635a8641SAndroid Build Coastguard Worker // what would need to change to turn that SingleThreadTaskRunner into a
31*635a8641SAndroid Build Coastguard Worker // SequencedTaskRunner for ease of scheduling as well as minimizes side-effects
32*635a8641SAndroid Build Coastguard Worker // if that change is made.
33*635a8641SAndroid Build Coastguard Worker //
34*635a8641SAndroid Build Coastguard Worker // Usage:
35*635a8641SAndroid Build Coastguard Worker //   class MyClass {
36*635a8641SAndroid Build Coastguard Worker //    public:
37*635a8641SAndroid Build Coastguard Worker //     MyClass() {
38*635a8641SAndroid Build Coastguard Worker //       // It's sometimes useful to detach on construction for objects that are
39*635a8641SAndroid Build Coastguard Worker //       // constructed in one place and forever after used from another
40*635a8641SAndroid Build Coastguard Worker //       // thread.
41*635a8641SAndroid Build Coastguard Worker //       DETACH_FROM_THREAD(my_thread_checker_);
42*635a8641SAndroid Build Coastguard Worker //     }
43*635a8641SAndroid Build Coastguard Worker //
44*635a8641SAndroid Build Coastguard Worker //     ~MyClass() {
45*635a8641SAndroid Build Coastguard Worker //       // ThreadChecker doesn't automatically check it's destroyed on origin
46*635a8641SAndroid Build Coastguard Worker //       // thread for the same reason it's sometimes detached in the
47*635a8641SAndroid Build Coastguard Worker //       // constructor. It's okay to destroy off thread if the owner otherwise
48*635a8641SAndroid Build Coastguard Worker //       // knows usage on the associated thread is done. If you're not
49*635a8641SAndroid Build Coastguard Worker //       // detaching in the constructor, you probably want to explicitly check
50*635a8641SAndroid Build Coastguard Worker //       // in the destructor.
51*635a8641SAndroid Build Coastguard Worker //       DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
52*635a8641SAndroid Build Coastguard Worker //     }
53*635a8641SAndroid Build Coastguard Worker //
54*635a8641SAndroid Build Coastguard Worker //     void MyMethod() {
55*635a8641SAndroid Build Coastguard Worker //       DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
56*635a8641SAndroid Build Coastguard Worker //       ... (do stuff) ...
57*635a8641SAndroid Build Coastguard Worker //     }
58*635a8641SAndroid Build Coastguard Worker //
59*635a8641SAndroid Build Coastguard Worker //    private:
60*635a8641SAndroid Build Coastguard Worker //     THREAD_CHECKER(my_thread_checker_);
61*635a8641SAndroid Build Coastguard Worker //   }
62*635a8641SAndroid Build Coastguard Worker 
63*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
64*635a8641SAndroid Build Coastguard Worker #define THREAD_CHECKER(name) base::ThreadChecker name
65*635a8641SAndroid Build Coastguard Worker #define DCHECK_CALLED_ON_VALID_THREAD(name) DCHECK((name).CalledOnValidThread())
66*635a8641SAndroid Build Coastguard Worker #define DETACH_FROM_THREAD(name) (name).DetachFromThread()
67*635a8641SAndroid Build Coastguard Worker #else  // DCHECK_IS_ON()
68*635a8641SAndroid Build Coastguard Worker #define THREAD_CHECKER(name)
69*635a8641SAndroid Build Coastguard Worker #define DCHECK_CALLED_ON_VALID_THREAD(name) EAT_STREAM_PARAMETERS
70*635a8641SAndroid Build Coastguard Worker #define DETACH_FROM_THREAD(name)
71*635a8641SAndroid Build Coastguard Worker #endif  // DCHECK_IS_ON()
72*635a8641SAndroid Build Coastguard Worker 
73*635a8641SAndroid Build Coastguard Worker namespace base {
74*635a8641SAndroid Build Coastguard Worker 
75*635a8641SAndroid Build Coastguard Worker // Do nothing implementation, for use in release mode.
76*635a8641SAndroid Build Coastguard Worker //
77*635a8641SAndroid Build Coastguard Worker // Note: You should almost always use the ThreadChecker class (through the above
78*635a8641SAndroid Build Coastguard Worker // macros) to get the right version for your build configuration.
79*635a8641SAndroid Build Coastguard Worker class ThreadCheckerDoNothing {
80*635a8641SAndroid Build Coastguard Worker  public:
81*635a8641SAndroid Build Coastguard Worker   ThreadCheckerDoNothing() = default;
CalledOnValidThread()82*635a8641SAndroid Build Coastguard Worker   bool CalledOnValidThread() const WARN_UNUSED_RESULT { return true; }
DetachFromThread()83*635a8641SAndroid Build Coastguard Worker   void DetachFromThread() {}
84*635a8641SAndroid Build Coastguard Worker 
85*635a8641SAndroid Build Coastguard Worker  private:
86*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ThreadCheckerDoNothing);
87*635a8641SAndroid Build Coastguard Worker };
88*635a8641SAndroid Build Coastguard Worker 
89*635a8641SAndroid Build Coastguard Worker // Note that ThreadCheckerImpl::CalledOnValidThread() returns false when called
90*635a8641SAndroid Build Coastguard Worker // from tasks posted to SingleThreadTaskRunners bound to different sequences,
91*635a8641SAndroid Build Coastguard Worker // even if the tasks happen to run on the same thread (e.g. two independent
92*635a8641SAndroid Build Coastguard Worker // SingleThreadTaskRunners on the TaskScheduler that happen to share a thread).
93*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
94*635a8641SAndroid Build Coastguard Worker class ThreadChecker : public ThreadCheckerImpl {
95*635a8641SAndroid Build Coastguard Worker };
96*635a8641SAndroid Build Coastguard Worker #else
97*635a8641SAndroid Build Coastguard Worker class ThreadChecker : public ThreadCheckerDoNothing {
98*635a8641SAndroid Build Coastguard Worker };
99*635a8641SAndroid Build Coastguard Worker #endif  // DCHECK_IS_ON()
100*635a8641SAndroid Build Coastguard Worker 
101*635a8641SAndroid Build Coastguard Worker }  // namespace base
102*635a8641SAndroid Build Coastguard Worker 
103*635a8641SAndroid Build Coastguard Worker #endif  // BASE_THREADING_THREAD_CHECKER_H_
104