// Copyright 2021 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef THIRD_PARTY_BLINK_WEBRTC_OVERRIDES_METRONOME_SOURCE_H_ #define THIRD_PARTY_BLINK_WEBRTC_OVERRIDES_METRONOME_SOURCE_H_ #include #include #include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_refptr.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "base/task/delayed_task_handle.h" #include "base/thread_annotations.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "third_party/webrtc/api/metronome/metronome.h" #include "third_party/webrtc/rtc_base/system/rtc_export.h" namespace blink { // The MetronomeSource ticks at a constant frequency, scheduling to wake up on // ticks where listeners have work to do, and not scheduling to wake up on ticks // where there is no work to do. // // When coalescing a large number of wakeup sources onto the MetronomeSource, // this should reduce package Idle Wake Ups with potential to improve // performance. // // The public API of this class is thread-safe and can be called from any // sequence. // // |webrtc_component| does not have a test binary. See // /third_party/blink/renderer/platform/peerconnection/metronome_source_test.cc // for testing. class RTC_EXPORT MetronomeSource final : public base::RefCountedThreadSafe { public: // Identifies a listener and controls when its callback should be active. class RTC_EXPORT ListenerHandle : public base::RefCountedThreadSafe { public: ListenerHandle(scoped_refptr metronome_source, scoped_refptr task_runner, base::RepeatingCallback callback, base::TimeTicks wakeup_time); // Sets the earliest time that the metronome may invoke the listener's // callback. If set to base::TimeTicks::Min(), the callback is called on // every metronome tick. If set to anything else, the callback is called a // single time until SetWakeupTime() is called again. void SetWakeupTime(base::TimeTicks wakeup_time); private: friend class base::RefCountedThreadSafe; friend class MetronomeSource; ~ListenerHandle(); void SetWakeUpTimeOnMetronomeTaskRunner(base::TimeTicks wakeup_time); void OnMetronomeTickOnMetronomeTaskRunner(base::TimeTicks now); void MaybeRunCallback(); void Inactivate(); const scoped_refptr metronome_source_; const scoped_refptr task_runner_; const base::RepeatingCallback callback_; base::Lock is_active_lock_; bool is_active_ GUARDED_BY(is_active_lock_) = true; // The earliest time to fire |callback_|. base::TimeTicks::Min() means to // fire on every tick, base::TimeTicks::Max() means never to fire. // Only touched on |metronome_source_->metronome_task_runner_|. base::TimeTicks wakeup_time_; }; // The tick phase. static base::TimeTicks Phase(); // The tick frequency. static base::TimeDelta Tick(); // The next metronome tick that is at or after |time|. static base::TimeTicks TimeSnappedToNextTick(base::TimeTicks time); MetronomeSource(); MetronomeSource(const MetronomeSource&) = delete; MetronomeSource& operator=(const MetronomeSource&) = delete; // Creates a new listener whose |callback| will be invoked on |task_runner|. // If |wakeup_time| is set to base::TimeTicks::Min() then the listener will be // called on every metronome tick. Otherwise |wakeup_time| is the earliest // time where the listener will be called a single time, after which // ListenerHandle::SetWakeupTime() has to be called for the listener to be // called again. scoped_refptr AddListener( scoped_refptr task_runner, base::RepeatingCallback callback, base::TimeTicks wakeup_time = base::TimeTicks::Min()); // After this call, the listener's callback is guaranteed not to be running // and won't ever run again. The listener can be removed from any thread, but // the listener cannot remove itself from within its own callback. void RemoveListener(scoped_refptr listener_handle); // Creates a webrtc::Metronome which is backed by this metronome. std::unique_ptr CreateWebRtcMetronome(); // Ensures the next tick is scheduled and get the time to advance to reach // that tick. After advancing mock time by the returned time delta, the next // tick is guaranteed to happen MetronomeTick::Tick() from now. base::TimeDelta EnsureNextTickAndGetDelayForTesting(); bool HasListenersForTesting(); private: friend class base::RefCountedThreadSafe; friend class ListenerHandle; ~MetronomeSource(); void AddListenerOnMetronomeTaskRunner( scoped_refptr listener_handle); void RemoveListenerOnMetronomeTaskRunner( scoped_refptr listener_handle); // Ensures the "next tick" is scheduled. The next tick is the next metronome // tick where we have work to do. If there is no work between now and // |wakeup_time| we will reschedule such that the next tick happens at or // after |wakeup_time|, but if there is already a tick scheduled earlier than // |wakeup_time| this is a NO-OP and more ticks may be needed before // |wakeup_time| is reached. void EnsureNextTickIsScheduled(base::TimeTicks wakeup_time); // |now_tick| is the time that this tick was scheduled to run, so it should be // very close to base::TimeTicks::Now() but is guaranteed to be aligned with // the current metronome tick. void OnMetronomeTick(base::TimeTicks now_tick); // All non-const members are only accessed on |metronome_task_runner_|. const scoped_refptr metronome_task_runner_; std::set> listeners_; base::DelayedTaskHandle next_tick_handle_; base::TimeTicks next_tick_ = base::TimeTicks::Min(); base::TimeTicks prev_tick_; }; } // namespace blink #endif // THIRD_PARTY_BLINK_WEBRTC_OVERRIDES_METRONOME_SOURCE_H_