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