blob: c4ad726f90c166f241f41a6b7c2698f3ad22c7b8 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
[email protected]399ed422012-12-27 19:58:002// 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_IMPL_H_
6#define BASE_SEQUENCE_CHECKER_IMPL_H_
7
François Doray62cb8e92024-06-05 14:49:028#include <cstdint>
tzik0c2fcf52017-02-16 08:52:319#include <memory>
François Doray62cb8e92024-06-05 14:49:0210#include <vector>
tzik0c2fcf52017-02-16 08:52:3111
[email protected]399ed422012-12-27 19:58:0012#include "base/base_export.h"
François Doray524d2a22024-01-04 09:54:1613#include "base/sequence_token.h"
[email protected]399ed422012-12-27 19:58:0014#include "base/synchronization/lock.h"
Aditya Keerthid2f44c72019-04-26 17:45:1415#include "base/thread_annotations.h"
François Doray524d2a22024-01-04 09:54:1616#include "base/threading/platform_thread_ref.h"
[email protected]399ed422012-12-27 19:58:0017
18namespace base {
danakj894364e2021-01-27 21:51:2919namespace debug {
20class StackTrace;
21}
[email protected]399ed422012-12-27 19:58:0022
François Doray62cb8e92024-06-05 14:49:0223// Real implementation of SequenceChecker.
fdorayeed5fa72016-07-26 22:28:4524//
François Doray62cb8e92024-06-05 14:49:0225// In most cases, SEQUENCE_CHECKER should be used instead of this, get the right
26// implementation for the build configuration. It's possible to temporarily use
27// this directly to get sequence checking in production builds, which can be
28// handy to debug issues only seen in the field. However, when used in a
29// non-DCHECK build, SequenceCheckerImpl::CalledOnValidSequence() will not
30// consider locks as a valid way to guarantee mutual exclusion (returns false if
31// not invoked from the bound sequence, even if all calls are made under the
32// same lock).
33
34// Marked with "context" capability to support thread_annotations.h.
Etienne Pierre-dorayf19e5742020-12-09 00:47:4335class THREAD_ANNOTATION_ATTRIBUTE__(capability("context"))
36 BASE_EXPORT SequenceCheckerImpl {
[email protected]399ed422012-12-27 19:58:0037 public:
danakj894364e2021-01-27 21:51:2938 static void EnableStackLogging();
39
[email protected]d52426c2013-07-30 19:26:4040 SequenceCheckerImpl();
[email protected]399ed422012-12-27 19:58:0041
Gabriel Charette9746ffce2019-07-30 20:27:1742 // Allow move construct/assign. This must be called on |other|'s associated
43 // sequence and assignment can only be made into a SequenceCheckerImpl which
44 // is detached or already associated with the current sequence. This isn't
45 // thread-safe (|this| and |other| shouldn't be in use while this move is
46 // performed). If the assignment was legal, the resulting SequenceCheckerImpl
47 // will be bound to the current sequence and |other| will be detached.
48 SequenceCheckerImpl(SequenceCheckerImpl&& other);
49 SequenceCheckerImpl& operator=(SequenceCheckerImpl&& other);
David Bienvenu5f4d4f02020-09-27 16:55:0350 SequenceCheckerImpl(const SequenceCheckerImpl&) = delete;
51 SequenceCheckerImpl& operator=(const SequenceCheckerImpl&) = delete;
52 ~SequenceCheckerImpl();
Gabriel Charette9746ffce2019-07-30 20:27:1753
fdorayeed5fa72016-07-26 22:28:4554 // Returns true if called in sequence with previous calls to this method and
55 // the constructor.
danakj894364e2021-01-27 21:51:2956 // On returning false, if logging is enabled with EnableStackLogging() and
57 // `out_bound_at` is not null, this method allocates a StackTrace and returns
58 // it in the out-parameter, storing inside it the stack from where the failing
59 // SequenceChecker was bound to its sequence. Otherwise, out_bound_at is left
60 // untouched.
Daniel Cheng4455c9842022-01-13 23:26:3761 [[nodiscard]] bool CalledOnValidSequence(
62 std::unique_ptr<debug::StackTrace>* out_bound_at = nullptr) const;
[email protected]399ed422012-12-27 19:58:0063
fdorayeed5fa72016-07-26 22:28:4564 // Unbinds the checker from the currently associated sequence. The checker
fdoraye2b19a12016-07-29 02:30:1665 // will be re-bound on the next call to CalledOnValidSequence().
[email protected]d52426c2013-07-30 19:26:4066 void DetachFromSequence();
[email protected]399ed422012-12-27 19:58:0067
68 private:
François Doray524d2a22024-01-04 09:54:1669 void EnsureAssigned() const EXCLUSIVE_LOCKS_REQUIRED(lock_);
70
71 // Members are mutable so that `CalledOnValidSequence()` can set them.
72
73 mutable Lock lock_;
74
75 // Stack from which this was bound (set if `EnableStackLogging()` was called).
76 mutable std::unique_ptr<debug::StackTrace> bound_at_ GUARDED_BY(lock_);
77
78 // Sequence to which this is bound.
79 mutable internal::SequenceToken sequence_token_ GUARDED_BY(lock_);
80
François Doray62cb8e92024-06-05 14:49:0281#if DCHECK_IS_ON()
82 // Locks to which this is bound.
83 mutable std::vector<uintptr_t> locks_ GUARDED_BY(lock_);
84#endif // DCHECK_IS_ON()
85
François Doray524d2a22024-01-04 09:54:1686 // Thread to which this is bound. Only used to evaluate
87 // `CalledOnValidSequence()` after TLS destruction.
88 mutable PlatformThreadRef thread_ref_ GUARDED_BY(lock_);
[email protected]399ed422012-12-27 19:58:0089};
90
91} // namespace base
92
93#endif // BASE_SEQUENCE_CHECKER_IMPL_H_