// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/quic/quic_chromium_alarm_factory.h" #include "base/check.h" #include "base/functional/bind.h" #include "base/location.h" #include "base/memory/raw_ptr.h" #include "base/task/sequenced_task_runner.h" #include "base/time/tick_clock.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "net/quic/platform/impl/quic_chromium_clock.h" namespace net { namespace { class QuicChromeAlarm : public quic::QuicAlarm, public base::TickClock { public: QuicChromeAlarm(const quic::QuicClock* clock, scoped_refptr task_runner, quic::QuicArenaScopedPtr delegate) : quic::QuicAlarm(std::move(delegate)), clock_(clock), // Unretained is safe because base::OneShotTimer never runs its task // after being deleted. on_alarm_callback_(base::BindRepeating(&QuicChromeAlarm::OnAlarm, base::Unretained(this))), timer_(std::make_unique(this)) { timer_->SetTaskRunner(std::move(task_runner)); } protected: void SetImpl() override { DCHECK(deadline().IsInitialized()); const int64_t delay_us = (deadline() - clock_->Now()).ToMicroseconds(); timer_->Start(FROM_HERE, base::Microseconds(delay_us), on_alarm_callback_); } void CancelImpl() override { DCHECK(!deadline().IsInitialized()); timer_->Stop(); } private: void OnAlarm() { DCHECK(deadline().IsInitialized()); // In tests, the time source used by the scheduler may not be in sync with // |clock_|. Because of this, the scheduler may run this task when // |clock->Now()| is smaller than |deadline()|. In that case, retry later. // This shouldn't happen in production. if (clock_->Now() < deadline()) { SetImpl(); return; } DCHECK_LE(deadline(), clock_->Now()); Fire(); } // base::TickClock: base::TimeTicks NowTicks() const override { return quic::QuicChromiumClock::QuicTimeToTimeTicks(clock_->Now()); } const raw_ptr clock_; base::RepeatingClosure on_alarm_callback_; const std::unique_ptr timer_; }; } // namespace QuicChromiumAlarmFactory::QuicChromiumAlarmFactory( base::SequencedTaskRunner* task_runner, const quic::QuicClock* clock) : task_runner_(task_runner), clock_(clock) {} QuicChromiumAlarmFactory::~QuicChromiumAlarmFactory() = default; quic::QuicArenaScopedPtr QuicChromiumAlarmFactory::CreateAlarm( quic::QuicArenaScopedPtr delegate, quic::QuicConnectionArena* arena) { if (arena != nullptr) { return arena->New(clock_, task_runner_, std::move(delegate)); } else { return quic::QuicArenaScopedPtr( new QuicChromeAlarm(clock_, task_runner_, std::move(delegate))); } } quic::QuicAlarm* QuicChromiumAlarmFactory::CreateAlarm( quic::QuicAlarm::Delegate* delegate) { return new QuicChromeAlarm( clock_, task_runner_, quic::QuicArenaScopedPtr(delegate)); } } // namespace net