blob: 6b4612839245222a2acf792097e55097aedd0461 [file] [log] [blame]
Artem Titovb586d822021-02-04 15:06:50 +01001/*
2 * Copyright 2019 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10#ifndef API_SEQUENCE_CHECKER_H_
11#define API_SEQUENCE_CHECKER_H_
12
13#include "rtc_base/checks.h"
14#include "rtc_base/synchronization/sequence_checker_internal.h"
15#include "rtc_base/thread_annotations.h"
16
17namespace webrtc {
18
19// SequenceChecker is a helper class used to help verify that some methods
20// of a class are called on the same task queue or thread. A
21// SequenceChecker is bound to a a task queue if the object is
22// created on a task queue, or a thread otherwise.
23//
24//
25// Example:
26// class MyClass {
27// public:
28// void Foo() {
29// RTC_DCHECK_RUN_ON(sequence_checker_);
30// ... (do stuff) ...
31// }
32//
33// private:
34// SequenceChecker sequence_checker_;
35// }
36//
37// In Release mode, IsCurrent will always return true.
38class RTC_LOCKABLE SequenceChecker
39#if RTC_DCHECK_IS_ON
40 : public webrtc_sequence_checker_internal::SequenceCheckerImpl {
41 using Impl = webrtc_sequence_checker_internal::SequenceCheckerImpl;
42#else
43 : public webrtc_sequence_checker_internal::SequenceCheckerDoNothing {
44 using Impl = webrtc_sequence_checker_internal::SequenceCheckerDoNothing;
45#endif
46 public:
47 // Returns true if sequence checker is attached to the current sequence.
48 bool IsCurrent() const { return Impl::IsCurrent(); }
49 // Detaches checker from sequence to which it is attached. Next attempt
50 // to do a check with this checker will result in attaching this checker
51 // to the sequence on which check was performed.
52 void Detach() { Impl::Detach(); }
53};
54
55} // namespace webrtc
56
57// RTC_RUN_ON/RTC_GUARDED_BY/RTC_DCHECK_RUN_ON macros allows to annotate
58// variables are accessed from same thread/task queue.
59// Using tools designed to check mutexes, it checks at compile time everywhere
60// variable is access, there is a run-time dcheck thread/task queue is correct.
61//
62// class SequenceCheckerExample {
63// public:
64// int CalledFromPacer() RTC_RUN_ON(pacer_sequence_checker_) {
65// return var2_;
66// }
67//
68// void CallMeFromPacer() {
69// RTC_DCHECK_RUN_ON(&pacer_sequence_checker_)
70// << "Should be called from pacer";
71// CalledFromPacer();
72// }
73//
74// private:
75// int pacer_var_ RTC_GUARDED_BY(pacer_sequence_checker_);
76// SequenceChecker pacer_sequence_checker_;
77// };
78//
79// class TaskQueueExample {
80// public:
81// class Encoder {
82// public:
83// rtc::TaskQueueBase& Queue() { return encoder_queue_; }
84// void Encode() {
85// RTC_DCHECK_RUN_ON(&encoder_queue_);
86// DoSomething(var_);
87// }
88//
89// private:
90// rtc::TaskQueueBase& encoder_queue_;
91// Frame var_ RTC_GUARDED_BY(encoder_queue_);
92// };
93//
94// void Encode() {
95// // Will fail at runtime when DCHECK is enabled:
96// // encoder_->Encode();
97// // Will work:
98// rtc::scoped_refptr<Encoder> encoder = encoder_;
99// encoder_->Queue().PostTask([encoder] { encoder->Encode(); });
100// }
101//
102// private:
103// rtc::scoped_refptr<Encoder> encoder_;
104// }
105
106// Document if a function expected to be called from same thread/task queue.
107#define RTC_RUN_ON(x) \
108 RTC_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x))
109
110#define RTC_DCHECK_RUN_ON(x) \
111 webrtc::webrtc_sequence_checker_internal::SequenceCheckerScope \
112 seq_check_scope(x); \
113 RTC_DCHECK((x)->IsCurrent()) \
114 << webrtc::webrtc_sequence_checker_internal::ExpectationToString(x)
115
116#endif // API_SEQUENCE_CHECKER_H_