blob: 66bdc83d21e142340686122415b89174232608bb [file] [log] [blame]
// 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 <atomic>
#include <set>
#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<MetronomeSource> {
public:
// Identifies a listener and controls when its callback should be active.
class RTC_EXPORT ListenerHandle
: public base::RefCountedThreadSafe<ListenerHandle> {
public:
ListenerHandle(scoped_refptr<MetronomeSource> metronome_source,
scoped_refptr<base::SequencedTaskRunner> task_runner,
base::RepeatingCallback<void()> 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<ListenerHandle>;
friend class MetronomeSource;
~ListenerHandle();
void SetWakeUpTimeOnMetronomeTaskRunner(base::TimeTicks wakeup_time);
void OnMetronomeTickOnMetronomeTaskRunner(base::TimeTicks now);
void MaybeRunCallback();
void Inactivate();
const scoped_refptr<MetronomeSource> metronome_source_;
const scoped_refptr<base::SequencedTaskRunner> task_runner_;
const base::RepeatingCallback<void()> 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<ListenerHandle> AddListener(
scoped_refptr<base::SequencedTaskRunner> task_runner,
base::RepeatingCallback<void()> 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<ListenerHandle> listener_handle);
// Creates a webrtc::Metronome which is backed by this metronome.
std::unique_ptr<webrtc::Metronome> 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<MetronomeSource>;
friend class ListenerHandle;
~MetronomeSource();
void AddListenerOnMetronomeTaskRunner(
scoped_refptr<ListenerHandle> listener_handle);
void RemoveListenerOnMetronomeTaskRunner(
scoped_refptr<ListenerHandle> 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<base::SequencedTaskRunner> metronome_task_runner_;
std::set<scoped_refptr<ListenerHandle>> 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_