| // 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, |
| base::SequencedTaskRunner* task_runner, |
| quic::QuicArenaScopedPtr<quic::QuicAlarm::Delegate> 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<base::OneShotTimer>(this)) { |
| timer_->SetTaskRunner(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<const quic::QuicClock> clock_; |
| base::RepeatingClosure on_alarm_callback_; |
| const std::unique_ptr<base::OneShotTimer> timer_; |
| }; |
| |
| } // namespace |
| |
| QuicChromiumAlarmFactory::QuicChromiumAlarmFactory( |
| base::SequencedTaskRunner* task_runner, |
| const quic::QuicClock* clock) |
| : task_runner_(task_runner), clock_(clock) {} |
| |
| QuicChromiumAlarmFactory::~QuicChromiumAlarmFactory() = default; |
| |
| quic::QuicArenaScopedPtr<quic::QuicAlarm> QuicChromiumAlarmFactory::CreateAlarm( |
| quic::QuicArenaScopedPtr<quic::QuicAlarm::Delegate> delegate, |
| quic::QuicConnectionArena* arena) { |
| if (arena != nullptr) { |
| return arena->New<QuicChromeAlarm>(clock_, task_runner_, |
| std::move(delegate)); |
| } else { |
| return quic::QuicArenaScopedPtr<quic::QuicAlarm>( |
| new QuicChromeAlarm(clock_, task_runner_, std::move(delegate))); |
| } |
| } |
| |
| quic::QuicAlarm* QuicChromiumAlarmFactory::CreateAlarm( |
| quic::QuicAlarm::Delegate* delegate) { |
| return new QuicChromeAlarm( |
| clock_, task_runner_, |
| quic::QuicArenaScopedPtr<quic::QuicAlarm::Delegate>(delegate)); |
| } |
| |
| } // namespace net |