tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sequence_checker.h (5131B)


      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 "api/task_queue/task_queue_base.h"
     14 #include "rtc_base/checks.h"
     15 #include "rtc_base/synchronization/sequence_checker_internal.h"
     16 #include "rtc_base/thread_annotations.h"
     17 
     18 namespace webrtc {
     19 
     20 // SequenceChecker is a helper class used to help verify that some methods
     21 // of a class are called on the same task queue or thread. A
     22 // SequenceChecker is bound to a a task queue if the object is
     23 // created on a task queue, or a thread otherwise.
     24 //
     25 //
     26 // Example:
     27 // class MyClass {
     28 //  public:
     29 //   void Foo() {
     30 //     RTC_DCHECK_RUN_ON(&sequence_checker_);
     31 //     ... (do stuff) ...
     32 //   }
     33 //
     34 //  private:
     35 //   SequenceChecker sequence_checker_;
     36 // }
     37 //
     38 // In Release mode, IsCurrent will always return true.
     39 class RTC_LOCKABLE SequenceChecker
     40 #if RTC_DCHECK_IS_ON
     41    : public webrtc_sequence_checker_internal::SequenceCheckerImpl {
     42  using Impl = webrtc_sequence_checker_internal::SequenceCheckerImpl;
     43 #else
     44    : public webrtc_sequence_checker_internal::SequenceCheckerDoNothing {
     45  using Impl = webrtc_sequence_checker_internal::SequenceCheckerDoNothing;
     46 #endif
     47 public:
     48  enum InitialState : bool { kDetached = false, kAttached = true };
     49 
     50  // TODO(tommi): We could maybe join these two ctors and have fewer factory
     51  // functions. At the moment they're separate to minimize code changes when
     52  // we added the second ctor as well as avoiding to have unnecessary code at
     53  // the SequenceChecker which much only run for the SequenceCheckerImpl
     54  // implementation.
     55  // In theory we could have something like:
     56  //
     57  //  SequenceChecker(InitialState initial_state = kAttached,
     58  //                  TaskQueueBase* attached_queue = TaskQueueBase::Current());
     59  //
     60  // But the problem with that is having the call to `Current()` exist for
     61  // `SequenceCheckerDoNothing`.
     62  explicit SequenceChecker(InitialState initial_state = kAttached)
     63      : Impl(initial_state) {}
     64  explicit SequenceChecker(TaskQueueBase* attached_queue)
     65      : Impl(attached_queue) {}
     66 
     67  // Returns true if sequence checker is attached to the current sequence.
     68  bool IsCurrent() const { return Impl::IsCurrent(); }
     69  // Detaches checker from sequence to which it is attached. Next attempt
     70  // to do a check with this checker will result in attaching this checker
     71  // to the sequence on which check was performed.
     72  void Detach() { Impl::Detach(); }
     73 };
     74 
     75 }  // namespace webrtc
     76 
     77 // RTC_RUN_ON/RTC_GUARDED_BY/RTC_DCHECK_RUN_ON macros allows to annotate
     78 // variables are accessed from same thread/task queue.
     79 // Using tools designed to check mutexes, it checks at compile time everywhere
     80 // variable is access, there is a run-time dcheck thread/task queue is correct.
     81 //
     82 // class SequenceCheckerExample {
     83 //  public:
     84 //   int CalledFromPacer() RTC_RUN_ON(pacer_sequence_checker_) {
     85 //     return var2_;
     86 //   }
     87 //
     88 //   void CallMeFromPacer() {
     89 //     RTC_DCHECK_RUN_ON(&pacer_sequence_checker_)
     90 //        << "Should be called from pacer";
     91 //     CalledFromPacer();
     92 //   }
     93 //
     94 //  private:
     95 //   int pacer_var_ RTC_GUARDED_BY(pacer_sequence_checker_);
     96 //   SequenceChecker pacer_sequence_checker_;
     97 // };
     98 //
     99 // class TaskQueueExample {
    100 //  public:
    101 //   class Encoder {
    102 //    public:
    103 //     webrtc::TaskQueueBase& Queue() { return encoder_queue_; }
    104 //     void Encode() {
    105 //       RTC_DCHECK_RUN_ON(&encoder_queue_);
    106 //       DoSomething(var_);
    107 //     }
    108 //
    109 //    private:
    110 //     webrtc::TaskQueueBase& encoder_queue_;
    111 //     Frame var_ RTC_GUARDED_BY(encoder_queue_);
    112 //   };
    113 //
    114 //   void Encode() {
    115 //     // Will fail at runtime when DCHECK is enabled:
    116 //     // encoder_->Encode();
    117 //     // Will work:
    118 //     webrtc::scoped_refptr<Encoder> encoder = encoder_;
    119 //     encoder_->Queue().PostTask([encoder] { encoder->Encode(); });
    120 //   }
    121 //
    122 //  private:
    123 //   webrtc::scoped_refptr<Encoder> encoder_;
    124 // }
    125 
    126 // Document if a function expected to be called from same thread/task queue.
    127 #define RTC_RUN_ON(x) \
    128  RTC_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x))
    129 
    130 // Checks current code is running on the desired sequence.
    131 //
    132 // First statement annotates for the thread safety analyzer the check was done.
    133 // Second statement validates it is running on the sequence `x`.
    134 // Such annotation has to be attached to a function, and that function has to be
    135 // called. Thus current implementation creates a noop lambda and calls it.
    136 #define RTC_DCHECK_RUN_ON(x)                                               \
    137  []() RTC_ASSERT_EXCLUSIVE_LOCK(x) {}();                                  \
    138  RTC_DCHECK((x)->IsCurrent())                                             \
    139      << webrtc::webrtc_sequence_checker_internal::ExpectationToString(x);
    140 
    141 #endif  // API_SEQUENCE_CHECKER_H_