xref: /aosp_15_r20/external/cronet/base/sequence_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_SEQUENCE_CHECKER_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_SEQUENCE_CHECKER_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/dcheck_is_on.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/macros/uniquify.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/sequence_checker_impl.h"
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker // SequenceChecker is a helper class used to help verify that some methods of a
14*6777b538SAndroid Build Coastguard Worker // class are called sequentially (for thread-safety). It supports thread safety
15*6777b538SAndroid Build Coastguard Worker // annotations (see base/thread_annotations.h).
16*6777b538SAndroid Build Coastguard Worker //
17*6777b538SAndroid Build Coastguard Worker // Use the macros below instead of the SequenceChecker directly so that the
18*6777b538SAndroid Build Coastguard Worker // unused member doesn't result in an extra byte (four when padded) per
19*6777b538SAndroid Build Coastguard Worker // instance in production.
20*6777b538SAndroid Build Coastguard Worker //
21*6777b538SAndroid Build Coastguard Worker // This class is much prefered to ThreadChecker for thread-safety checks.
22*6777b538SAndroid Build Coastguard Worker // ThreadChecker should only be used for classes that are truly thread-affine
23*6777b538SAndroid Build Coastguard Worker // (use thread-local-storage or a third-party API that does).
24*6777b538SAndroid Build Coastguard Worker //
25*6777b538SAndroid Build Coastguard Worker // Debugging:
26*6777b538SAndroid Build Coastguard Worker //   If SequenceChecker::EnableStackLogging() is called beforehand, then when
27*6777b538SAndroid Build Coastguard Worker //   SequenceChecker fails, in addition to crashing with a stack trace of where
28*6777b538SAndroid Build Coastguard Worker //   the violation occurred, it will also dump a stack trace of where the
29*6777b538SAndroid Build Coastguard Worker //   checker was bound to a sequence.
30*6777b538SAndroid Build Coastguard Worker //
31*6777b538SAndroid Build Coastguard Worker // Usage:
32*6777b538SAndroid Build Coastguard Worker //   class MyClass {
33*6777b538SAndroid Build Coastguard Worker //    public:
34*6777b538SAndroid Build Coastguard Worker //     MyClass() {
35*6777b538SAndroid Build Coastguard Worker //       // Detaching on construction is necessary for objects that are
36*6777b538SAndroid Build Coastguard Worker //       // constructed on one sequence and forever after used from another
37*6777b538SAndroid Build Coastguard Worker //       // sequence.
38*6777b538SAndroid Build Coastguard Worker //       DETACH_FROM_SEQUENCE(my_sequence_checker_);
39*6777b538SAndroid Build Coastguard Worker //     }
40*6777b538SAndroid Build Coastguard Worker //
41*6777b538SAndroid Build Coastguard Worker //     ~MyClass() {
42*6777b538SAndroid Build Coastguard Worker //       // SequenceChecker doesn't automatically check it's destroyed on origin
43*6777b538SAndroid Build Coastguard Worker //       // sequence for the same reason it's sometimes detached in the
44*6777b538SAndroid Build Coastguard Worker //       // constructor. It's okay to destroy off sequence if the owner
45*6777b538SAndroid Build Coastguard Worker //       // otherwise knows usage on the associated sequence is done. If you're
46*6777b538SAndroid Build Coastguard Worker //       // not detaching in the constructor, you probably want to explicitly
47*6777b538SAndroid Build Coastguard Worker //       // check in the destructor.
48*6777b538SAndroid Build Coastguard Worker //       DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
49*6777b538SAndroid Build Coastguard Worker //     }
50*6777b538SAndroid Build Coastguard Worker //     void MyMethod() {
51*6777b538SAndroid Build Coastguard Worker //       DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
52*6777b538SAndroid Build Coastguard Worker //       ... (do stuff) ...
53*6777b538SAndroid Build Coastguard Worker //       MyOtherMethod();
54*6777b538SAndroid Build Coastguard Worker //     }
55*6777b538SAndroid Build Coastguard Worker //
56*6777b538SAndroid Build Coastguard Worker //     void MyOtherMethod()
57*6777b538SAndroid Build Coastguard Worker //         VALID_CONTEXT_REQUIRED(my_sequence_checker_) {
58*6777b538SAndroid Build Coastguard Worker //       foo_ = 42;
59*6777b538SAndroid Build Coastguard Worker //     }
60*6777b538SAndroid Build Coastguard Worker //
61*6777b538SAndroid Build Coastguard Worker //    private:
62*6777b538SAndroid Build Coastguard Worker //      // GUARDED_BY_CONTEXT() enforces that this member is only
63*6777b538SAndroid Build Coastguard Worker //      // accessed from a scope that invokes DCHECK_CALLED_ON_VALID_SEQUENCE()
64*6777b538SAndroid Build Coastguard Worker //      // or from a function annotated with VALID_CONTEXT_REQUIRED(). A
65*6777b538SAndroid Build Coastguard Worker //      // DCHECK build will not compile if the member is accessed and these
66*6777b538SAndroid Build Coastguard Worker //      // conditions are not met.
67*6777b538SAndroid Build Coastguard Worker //     int foo_ GUARDED_BY_CONTEXT(my_sequence_checker_);
68*6777b538SAndroid Build Coastguard Worker //
69*6777b538SAndroid Build Coastguard Worker //     SEQUENCE_CHECKER(my_sequence_checker_);
70*6777b538SAndroid Build Coastguard Worker //   }
71*6777b538SAndroid Build Coastguard Worker 
72*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
73*6777b538SAndroid Build Coastguard Worker #define SEQUENCE_CHECKER(name) base::SequenceChecker name
74*6777b538SAndroid Build Coastguard Worker #define DCHECK_CALLED_ON_VALID_SEQUENCE(name, ...)   \
75*6777b538SAndroid Build Coastguard Worker   base::ScopedValidateSequenceChecker BASE_UNIQUIFY( \
76*6777b538SAndroid Build Coastguard Worker       scoped_validate_sequence_checker_)(name, ##__VA_ARGS__)
77*6777b538SAndroid Build Coastguard Worker #define DETACH_FROM_SEQUENCE(name) (name).DetachFromSequence()
78*6777b538SAndroid Build Coastguard Worker #else  // DCHECK_IS_ON()
79*6777b538SAndroid Build Coastguard Worker // A no-op expansion that can be followed by a semicolon at class level.
80*6777b538SAndroid Build Coastguard Worker #define SEQUENCE_CHECKER(name) static_assert(true, "")
81*6777b538SAndroid Build Coastguard Worker #define DCHECK_CALLED_ON_VALID_SEQUENCE(name, ...) EAT_CHECK_STREAM_PARAMS()
82*6777b538SAndroid Build Coastguard Worker #define DETACH_FROM_SEQUENCE(name)
83*6777b538SAndroid Build Coastguard Worker #endif  // DCHECK_IS_ON()
84*6777b538SAndroid Build Coastguard Worker 
85*6777b538SAndroid Build Coastguard Worker namespace base {
86*6777b538SAndroid Build Coastguard Worker 
87*6777b538SAndroid Build Coastguard Worker // Do nothing implementation, for use in release mode.
88*6777b538SAndroid Build Coastguard Worker //
89*6777b538SAndroid Build Coastguard Worker // Note: You should almost always use the SequenceChecker class (through the
90*6777b538SAndroid Build Coastguard Worker // above macros) to get the right version for your build configuration.
91*6777b538SAndroid Build Coastguard Worker // Note: This is marked with "context" capability in order to support
92*6777b538SAndroid Build Coastguard Worker // thread_annotations.h.
93*6777b538SAndroid Build Coastguard Worker class THREAD_ANNOTATION_ATTRIBUTE__(capability("context"))
94*6777b538SAndroid Build Coastguard Worker     SequenceCheckerDoNothing {
95*6777b538SAndroid Build Coastguard Worker  public:
EnableStackLogging()96*6777b538SAndroid Build Coastguard Worker   static void EnableStackLogging() {}
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker   SequenceCheckerDoNothing() = default;
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker   // Moving between matching sequences is allowed to help classes with
101*6777b538SAndroid Build Coastguard Worker   // SequenceCheckers that want a default move-construct/assign.
102*6777b538SAndroid Build Coastguard Worker   SequenceCheckerDoNothing(SequenceCheckerDoNothing&& other) = default;
103*6777b538SAndroid Build Coastguard Worker   SequenceCheckerDoNothing& operator=(SequenceCheckerDoNothing&& other) =
104*6777b538SAndroid Build Coastguard Worker       default;
105*6777b538SAndroid Build Coastguard Worker   SequenceCheckerDoNothing(const SequenceCheckerDoNothing&) = delete;
106*6777b538SAndroid Build Coastguard Worker   SequenceCheckerDoNothing& operator=(const SequenceCheckerDoNothing&) = delete;
107*6777b538SAndroid Build Coastguard Worker 
108*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool CalledOnValidSequence(void* = nullptr) const {
109*6777b538SAndroid Build Coastguard Worker     return true;
110*6777b538SAndroid Build Coastguard Worker   }
DetachFromSequence()111*6777b538SAndroid Build Coastguard Worker   void DetachFromSequence() {}
112*6777b538SAndroid Build Coastguard Worker };
113*6777b538SAndroid Build Coastguard Worker 
114*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
115*6777b538SAndroid Build Coastguard Worker using SequenceChecker = SequenceCheckerImpl;
116*6777b538SAndroid Build Coastguard Worker #else
117*6777b538SAndroid Build Coastguard Worker using SequenceChecker = SequenceCheckerDoNothing;
118*6777b538SAndroid Build Coastguard Worker #endif  // DCHECK_IS_ON()
119*6777b538SAndroid Build Coastguard Worker 
120*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
121*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT SCOPED_LOCKABLE ScopedValidateSequenceChecker {
122*6777b538SAndroid Build Coastguard Worker  public:
123*6777b538SAndroid Build Coastguard Worker   explicit ScopedValidateSequenceChecker(const SequenceChecker& checker)
124*6777b538SAndroid Build Coastguard Worker       EXCLUSIVE_LOCK_FUNCTION(checker);
125*6777b538SAndroid Build Coastguard Worker   ~ScopedValidateSequenceChecker() UNLOCK_FUNCTION();
126*6777b538SAndroid Build Coastguard Worker };
127*6777b538SAndroid Build Coastguard Worker #endif
128*6777b538SAndroid Build Coastguard Worker 
129*6777b538SAndroid Build Coastguard Worker }  // namespace base
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker #endif  // BASE_SEQUENCE_CHECKER_H_
132