blob: 8477dde73ed2f15e8516d727115fb24580a224bf [file] [log] [blame]
[email protected]399ed422012-12-27 19:58:001// 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
gabe66aa552017-05-26 17:20:588#include "base/compiler_specific.h"
gabd52c912a2017-05-11 04:15:599#include "base/logging.h"
[email protected]399ed422012-12-27 19:58:0010#include "base/sequence_checker_impl.h"
Nico Weber6065c402019-03-19 21:56:4211#include "build/build_config.h"
[email protected]399ed422012-12-27 19:58:0012
gabd52c912a2017-05-11 04:15:5913// SequenceChecker is a helper class used to help verify that some methods of a
14// class are called sequentially (for thread-safety).
15//
16// Use the macros below instead of the SequenceChecker directly so that the
17// unused member doesn't result in an extra byte (four when padded) per
18// instance in production.
19//
20// This class is much prefered to ThreadChecker for thread-safety checks.
21// ThreadChecker should only be used for classes that are truly thread-affine
22// (use thread-local-storage or a third-party API that does).
23//
24// Usage:
25// class MyClass {
26// public:
27// MyClass() {
28// // It's sometimes useful to detach on construction for objects that are
29// // constructed in one place and forever after used from another
30// // sequence.
31// DETACH_FROM_SEQUENCE(my_sequence_checker_);
32// }
33//
34// ~MyClass() {
35// // SequenceChecker doesn't automatically check it's destroyed on origin
36// // sequence for the same reason it's sometimes detached in the
37// // constructor. It's okay to destroy off sequence if the owner
38// // otherwise knows usage on the associated sequence is done. If you're
39// // not detaching in the constructor, you probably want to explicitly
40// // check in the destructor.
Christian Fremerey177b9b932017-06-02 16:55:0241// DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
gabd52c912a2017-05-11 04:15:5942// }
43// void MyMethod() {
44// DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
45// ... (do stuff) ...
46// }
47//
48// private:
49// SEQUENCE_CHECKER(my_sequence_checker_);
50// }
51
52#if DCHECK_IS_ON()
53#define SEQUENCE_CHECKER(name) base::SequenceChecker name
54#define DCHECK_CALLED_ON_VALID_SEQUENCE(name) \
55 DCHECK((name).CalledOnValidSequence())
56#define DETACH_FROM_SEQUENCE(name) (name).DetachFromSequence()
57#else // DCHECK_IS_ON()
Jose Dapena Paz59a93672019-04-08 17:54:4158#if __OBJC__ && defined(OS_IOS) && !HAS_FEATURE(objc_cxx_static_assert)
Nico Weber6065c402019-03-19 21:56:4259// TODO(thakis): Remove this branch once Xcode's clang has clang r356148.
Nico Weberea0dd1a2019-03-01 17:04:4160#define SEQUENCE_CHECKER(name)
Nico Weberdcacb332019-03-09 02:32:0261#else
62#define SEQUENCE_CHECKER(name) static_assert(true, "")
63#endif
Kevin Marshalle6572ee2017-05-31 01:02:0464#define DCHECK_CALLED_ON_VALID_SEQUENCE(name) EAT_STREAM_PARAMETERS
gabd52c912a2017-05-11 04:15:5965#define DETACH_FROM_SEQUENCE(name)
66#endif // DCHECK_IS_ON()
67
[email protected]399ed422012-12-27 19:58:0068namespace base {
69
[email protected]399ed422012-12-27 19:58:0070// Do nothing implementation, for use in release mode.
71//
gabd52c912a2017-05-11 04:15:5972// Note: You should almost always use the SequenceChecker class (through the
73// above macros) to get the right version for your build configuration.
[email protected]399ed422012-12-27 19:58:0074class SequenceCheckerDoNothing {
75 public:
tzikc342ef572017-07-21 08:09:5076 SequenceCheckerDoNothing() = default;
Gabriel Charette9746ffce2019-07-30 20:27:1777
78 // Moving between matching sequences is allowed to help classes with
79 // SequenceCheckers that want a default move-construct/assign.
80 SequenceCheckerDoNothing(SequenceCheckerDoNothing&& other) = default;
81 SequenceCheckerDoNothing& operator=(SequenceCheckerDoNothing&& other) =
82 default;
83
gabe66aa552017-05-26 17:20:5884 bool CalledOnValidSequence() const WARN_UNUSED_RESULT { return true; }
[email protected]d52426c2013-07-30 19:26:4085 void DetachFromSequence() {}
tzikc342ef572017-07-21 08:09:5086
87 private:
88 DISALLOW_COPY_AND_ASSIGN(SequenceCheckerDoNothing);
[email protected]399ed422012-12-27 19:58:0089};
90
gab190f7542016-08-01 20:03:4191#if DCHECK_IS_ON()
[email protected]399ed422012-12-27 19:58:0092class SequenceChecker : public SequenceCheckerImpl {
[email protected]399ed422012-12-27 19:58:0093};
94#else
95class SequenceChecker : public SequenceCheckerDoNothing {
[email protected]399ed422012-12-27 19:58:0096};
gab190f7542016-08-01 20:03:4197#endif // DCHECK_IS_ON()
[email protected]399ed422012-12-27 19:58:0098
99} // namespace base
100
101#endif // BASE_SEQUENCE_CHECKER_H_