[go: nahoru, domu]

blob: dd18f1e04c230399bdfb15b351b006663c973b77 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// 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_LOW_PRECISION_TIMER_H_
#define THIRD_PARTY_BLINK_WEBRTC_OVERRIDES_LOW_PRECISION_TIMER_H_
#include "base/feature_list.h"
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
#include "base/task/sequenced_task_runner.h"
#include "base/thread_annotations.h"
#include "base/time/time.h"
#include "third_party/webrtc/rtc_base/system/rtc_export.h"
#include "third_party/webrtc_overrides/metronome_source.h"
namespace blink {
// Implements a low precision timer, expect it to fire up to ~16 ms late (plus
// any OS or workload related delays).
//
// This timer only fires on metronome ticks as specified by
// MetronomeSource::TimeSnappedToNextTick(). This allows running numerous timers
// without increasing the Idle Wake Ups frequency beyond the metronome tick
// frequency, i.e. when each tick is already scheduled adding a
// LowPrecisionTimer should not add any Idle Wake Ups.
//
// TODO(https://crbug.com/1267874): Can this timer be moved to base/ or replaced
// by a low precision base/ timer without causing excessive Idle Wake Up
// frequencies (e.g. WebRTC use case with 50 incoming videos)?
class RTC_EXPORT LowPrecisionTimer final {
public:
LowPrecisionTimer(scoped_refptr<base::SequencedTaskRunner> task_runner,
base::RepeatingCallback<void()> callback);
~LowPrecisionTimer();
// Must be called prior to destruction. Unregisters from the metronome
// provider.
void Shutdown();
// Schedules to invoke the callback |delay| time from now.
void StartOneShot(base::TimeDelta delay);
// Scheduldes to repeat unconditionally until the timer is stopped. This has
// the same behavior as calling StartOneShot(delay) inside each callback.
void StartRepeating(base::TimeDelta delay);
// True if there is currently activity scheduled.
bool IsActive();
// Cancels any scheduled callbacks.
void Stop();
// Change which task runner to fire callbacks on. Seamlessy re-schedules
// pending callbacks. Must not be called from inside the callback.
void MoveToNewTaskRunner(
scoped_refptr<base::SequencedTaskRunner> task_runner);
private:
// Handles the scheduling and cancellation of a repeating callback.
// The callback can be re-scheduled after it has fired, but all other settings
// are "const". To change settings the SchedulableCallback has to be
// inactivated and replaced by a new SchedulableCallback instance.
class SchedulableCallback
: public base::RefCountedThreadSafe<SchedulableCallback> {
public:
SchedulableCallback(scoped_refptr<base::SequencedTaskRunner> task_runner,
base::RepeatingCallback<void()> callback,
base::TimeDelta repeated_delay);
~SchedulableCallback();
// The task can be re-scheduled after each run.
void Schedule(base::TimeTicks scheduled_time);
bool IsScheduled();
// Inactivate the callback. Returns the cancelled scheduled time, or
// base::TimeTicks::Max() if nothing was scheduled when cancelled.
base::TimeTicks Inactivate();
private:
void MaybeRun();
void RemoveMetronomeListener();
const scoped_refptr<base::SequencedTaskRunner> task_runner_;
const base::RepeatingCallback<void()> callback_;
// Only accessed on |task_runner_|.
bool is_currently_running_ = false;
base::Lock active_lock_;
// Guarded by |active_lock_|, but to avoid deadlock we do not acquire the
// lock when Inactivate() is being called from inside the callback. In this
// case the lock is already being held by MaybeRun().
bool is_active_ = true;
base::TimeDelta repeated_delay_;
base::Lock scheduled_time_lock_;
base::TimeTicks scheduled_time_ GUARDED_BY(scheduled_time_lock_) =
base::TimeTicks::Max(); // Max represents forever, i.e. not scheduled.
};
// Lazy-constructs |schedulable_callback_| and schedules the callback on the
// specified time.
void ScheduleCallback(base::TimeTicks scheduled_time)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
// Inactivates in-flight callbacks and re-schedulels the callback using the
// latest settings. Used e.g. when we start or stop using the metronome.
void RescheduleCallback() EXCLUSIVE_LOCKS_REQUIRED(lock_);
const base::RepeatingCallback<void()> callback_;
base::Lock lock_;
bool is_shutdown_ GUARDED_BY(lock_) = false;
scoped_refptr<base::SequencedTaskRunner> task_runner_ GUARDED_BY(lock_);
scoped_refptr<SchedulableCallback> schedulable_callback_ GUARDED_BY(lock_);
// If not repeating this is zero.
base::TimeDelta repeated_delay_ GUARDED_BY(lock_);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_WEBRTC_OVERRIDES_LOW_PRECISION_TIMER_H_