xref: /aosp_15_r20/external/webrtc/api/sequence_checker.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
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 
17 namespace 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.
38 class 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.
IsCurrent()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.
Detach()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 // Checks current code is running on the desired sequence.
111 //
112 // First statement validates it is running on the sequence `x`.
113 // Second statement annotates for the thread safety analyzer the check was done.
114 // Such annotation has to be attached to a function, and that function has to be
115 // called. Thus current implementation creates a noop lambda and calls it.
116 #define RTC_DCHECK_RUN_ON(x)                                               \
117   RTC_DCHECK((x)->IsCurrent())                                             \
118       << webrtc::webrtc_sequence_checker_internal::ExpectationToString(x); \
119   []() RTC_ASSERT_EXCLUSIVE_LOCK(x) {}()
120 
121 #endif  // API_SEQUENCE_CHECKER_H_
122