1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_SEQUENCE_CHECKER_H_ 6 #define BASE_SEQUENCE_CHECKER_H_ 7 8 #include "base/compiler_specific.h" 9 #include "base/logging.h" 10 #include "base/sequence_checker_impl.h" 11 12 // SequenceChecker is a helper class used to help verify that some methods of a 13 // class are called sequentially (for thread-safety). 14 // 15 // Use the macros below instead of the SequenceChecker directly so that the 16 // unused member doesn't result in an extra byte (four when padded) per 17 // instance in production. 18 // 19 // This class is much prefered to ThreadChecker for thread-safety checks. 20 // ThreadChecker should only be used for classes that are truly thread-affine 21 // (use thread-local-storage or a third-party API that does). 22 // 23 // Usage: 24 // class MyClass { 25 // public: 26 // MyClass() { 27 // // It's sometimes useful to detach on construction for objects that are 28 // // constructed in one place and forever after used from another 29 // // sequence. 30 // DETACH_FROM_SEQUENCE(my_sequence_checker_); 31 // } 32 // 33 // ~MyClass() { 34 // // SequenceChecker doesn't automatically check it's destroyed on origin 35 // // sequence for the same reason it's sometimes detached in the 36 // // constructor. It's okay to destroy off sequence if the owner 37 // // otherwise knows usage on the associated sequence is done. If you're 38 // // not detaching in the constructor, you probably want to explicitly 39 // // check in the destructor. 40 // DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_); 41 // } 42 // void MyMethod() { 43 // DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_); 44 // ... (do stuff) ... 45 // } 46 // 47 // private: 48 // SEQUENCE_CHECKER(my_sequence_checker_); 49 // } 50 51 #if DCHECK_IS_ON() 52 #define SEQUENCE_CHECKER(name) base::SequenceChecker name 53 #define DCHECK_CALLED_ON_VALID_SEQUENCE(name) \ 54 DCHECK((name).CalledOnValidSequence()) 55 #define DETACH_FROM_SEQUENCE(name) (name).DetachFromSequence() 56 #else // DCHECK_IS_ON() 57 #define SEQUENCE_CHECKER(name) 58 #define DCHECK_CALLED_ON_VALID_SEQUENCE(name) EAT_STREAM_PARAMETERS 59 #define DETACH_FROM_SEQUENCE(name) 60 #endif // DCHECK_IS_ON() 61 62 namespace base { 63 64 // Do nothing implementation, for use in release mode. 65 // 66 // Note: You should almost always use the SequenceChecker class (through the 67 // above macros) to get the right version for your build configuration. 68 class SequenceCheckerDoNothing { 69 public: 70 SequenceCheckerDoNothing() = default; CalledOnValidSequence()71 bool CalledOnValidSequence() const WARN_UNUSED_RESULT { return true; } DetachFromSequence()72 void DetachFromSequence() {} 73 74 private: 75 DISALLOW_COPY_AND_ASSIGN(SequenceCheckerDoNothing); 76 }; 77 78 #if DCHECK_IS_ON() 79 class SequenceChecker : public SequenceCheckerImpl { 80 }; 81 #else 82 class SequenceChecker : public SequenceCheckerDoNothing { 83 }; 84 #endif // DCHECK_IS_ON() 85 86 } // namespace base 87 88 #endif // BASE_SEQUENCE_CHECKER_H_ 89