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