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_IMPL_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_SEQUENCE_CHECKER_IMPL_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <memory> 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h" 11*6777b538SAndroid Build Coastguard Worker #include "base/sequence_token.h" 12*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h" 13*6777b538SAndroid Build Coastguard Worker #include "base/thread_annotations.h" 14*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread_ref.h" 15*6777b538SAndroid Build Coastguard Worker 16*6777b538SAndroid Build Coastguard Worker namespace base { 17*6777b538SAndroid Build Coastguard Worker namespace debug { 18*6777b538SAndroid Build Coastguard Worker class StackTrace; 19*6777b538SAndroid Build Coastguard Worker } 20*6777b538SAndroid Build Coastguard Worker 21*6777b538SAndroid Build Coastguard Worker // Real implementation of SequenceChecker for use in debug mode or for temporary 22*6777b538SAndroid Build Coastguard Worker // use in release mode (e.g. to CHECK on a threading issue seen only in the 23*6777b538SAndroid Build Coastguard Worker // wild). 24*6777b538SAndroid Build Coastguard Worker // 25*6777b538SAndroid Build Coastguard Worker // Note: You should almost always use the SequenceChecker class to get the right 26*6777b538SAndroid Build Coastguard Worker // version for your build configuration. 27*6777b538SAndroid Build Coastguard Worker // Note: This is marked with "context" capability in order to support 28*6777b538SAndroid Build Coastguard Worker // thread_annotations.h. 29*6777b538SAndroid Build Coastguard Worker class THREAD_ANNOTATION_ATTRIBUTE__(capability("context")) 30*6777b538SAndroid Build Coastguard Worker BASE_EXPORT SequenceCheckerImpl { 31*6777b538SAndroid Build Coastguard Worker public: 32*6777b538SAndroid Build Coastguard Worker static void EnableStackLogging(); 33*6777b538SAndroid Build Coastguard Worker 34*6777b538SAndroid Build Coastguard Worker SequenceCheckerImpl(); 35*6777b538SAndroid Build Coastguard Worker 36*6777b538SAndroid Build Coastguard Worker // Allow move construct/assign. This must be called on |other|'s associated 37*6777b538SAndroid Build Coastguard Worker // sequence and assignment can only be made into a SequenceCheckerImpl which 38*6777b538SAndroid Build Coastguard Worker // is detached or already associated with the current sequence. This isn't 39*6777b538SAndroid Build Coastguard Worker // thread-safe (|this| and |other| shouldn't be in use while this move is 40*6777b538SAndroid Build Coastguard Worker // performed). If the assignment was legal, the resulting SequenceCheckerImpl 41*6777b538SAndroid Build Coastguard Worker // will be bound to the current sequence and |other| will be detached. 42*6777b538SAndroid Build Coastguard Worker SequenceCheckerImpl(SequenceCheckerImpl&& other); 43*6777b538SAndroid Build Coastguard Worker SequenceCheckerImpl& operator=(SequenceCheckerImpl&& other); 44*6777b538SAndroid Build Coastguard Worker SequenceCheckerImpl(const SequenceCheckerImpl&) = delete; 45*6777b538SAndroid Build Coastguard Worker SequenceCheckerImpl& operator=(const SequenceCheckerImpl&) = delete; 46*6777b538SAndroid Build Coastguard Worker ~SequenceCheckerImpl(); 47*6777b538SAndroid Build Coastguard Worker 48*6777b538SAndroid Build Coastguard Worker // Returns true if called in sequence with previous calls to this method and 49*6777b538SAndroid Build Coastguard Worker // the constructor. 50*6777b538SAndroid Build Coastguard Worker // On returning false, if logging is enabled with EnableStackLogging() and 51*6777b538SAndroid Build Coastguard Worker // `out_bound_at` is not null, this method allocates a StackTrace and returns 52*6777b538SAndroid Build Coastguard Worker // it in the out-parameter, storing inside it the stack from where the failing 53*6777b538SAndroid Build Coastguard Worker // SequenceChecker was bound to its sequence. Otherwise, out_bound_at is left 54*6777b538SAndroid Build Coastguard Worker // untouched. 55*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool CalledOnValidSequence( 56*6777b538SAndroid Build Coastguard Worker std::unique_ptr<debug::StackTrace>* out_bound_at = nullptr) const; 57*6777b538SAndroid Build Coastguard Worker 58*6777b538SAndroid Build Coastguard Worker // Unbinds the checker from the currently associated sequence. The checker 59*6777b538SAndroid Build Coastguard Worker // will be re-bound on the next call to CalledOnValidSequence(). 60*6777b538SAndroid Build Coastguard Worker void DetachFromSequence(); 61*6777b538SAndroid Build Coastguard Worker 62*6777b538SAndroid Build Coastguard Worker private: 63*6777b538SAndroid Build Coastguard Worker void EnsureAssigned() const EXCLUSIVE_LOCKS_REQUIRED(lock_); 64*6777b538SAndroid Build Coastguard Worker 65*6777b538SAndroid Build Coastguard Worker // Members are mutable so that `CalledOnValidSequence()` can set them. 66*6777b538SAndroid Build Coastguard Worker 67*6777b538SAndroid Build Coastguard Worker mutable Lock lock_; 68*6777b538SAndroid Build Coastguard Worker 69*6777b538SAndroid Build Coastguard Worker // Stack from which this was bound (set if `EnableStackLogging()` was called). 70*6777b538SAndroid Build Coastguard Worker mutable std::unique_ptr<debug::StackTrace> bound_at_ GUARDED_BY(lock_); 71*6777b538SAndroid Build Coastguard Worker 72*6777b538SAndroid Build Coastguard Worker // Sequence to which this is bound. 73*6777b538SAndroid Build Coastguard Worker mutable internal::SequenceToken sequence_token_ GUARDED_BY(lock_); 74*6777b538SAndroid Build Coastguard Worker 75*6777b538SAndroid Build Coastguard Worker // Thread to which this is bound. Only used to evaluate 76*6777b538SAndroid Build Coastguard Worker // `CalledOnValidSequence()` after TLS destruction. 77*6777b538SAndroid Build Coastguard Worker mutable PlatformThreadRef thread_ref_ GUARDED_BY(lock_); 78*6777b538SAndroid Build Coastguard Worker }; 79*6777b538SAndroid Build Coastguard Worker 80*6777b538SAndroid Build Coastguard Worker } // namespace base 81*6777b538SAndroid Build Coastguard Worker 82*6777b538SAndroid Build Coastguard Worker #endif // BASE_SEQUENCE_CHECKER_IMPL_H_ 83