Index: net/quic/quic_chromium_alarm_factory.cc |
diff --git a/net/quic/quic_chromium_alarm_factory.cc b/net/quic/quic_chromium_alarm_factory.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8973b97e35c150417df7a0aadc7829bacf437acc |
--- /dev/null |
+++ b/net/quic/quic_chromium_alarm_factory.cc |
@@ -0,0 +1,117 @@ |
+// Copyright (c) 2012 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. |
+ |
+#include "net/quic/quic_chromium_alarm_factory.h" |
+ |
+#include "base/bind.h" |
+#include "base/location.h" |
+#include "base/logging.h" |
+#include "base/metrics/sparse_histogram.h" |
+#include "base/task_runner.h" |
+#include "base/time/time.h" |
+ |
+namespace net { |
+ |
+namespace { |
+ |
+class QuicChromeAlarm : public QuicAlarm { |
+ public: |
+ QuicChromeAlarm(const QuicClock* clock, |
+ base::TaskRunner* task_runner, |
+ QuicArenaScopedPtr<QuicAlarm::Delegate> delegate) |
+ : QuicAlarm(std::move(delegate)), |
+ clock_(clock), |
+ task_runner_(task_runner), |
+ task_deadline_(QuicTime::Zero()), |
+ weak_factory_(this) {} |
+ |
+ protected: |
+ void SetImpl() override { |
+ DCHECK(deadline().IsInitialized()); |
+ if (task_deadline_.IsInitialized()) { |
+ if (task_deadline_ <= deadline()) { |
+ // Since tasks can not be un-posted, OnAlarm will be invoked which |
+ // will notice that deadline has not yet been reached, and will set |
+ // the alarm for the new deadline. |
+ return; |
+ } |
+ // The scheduled task is after new deadline. Invalidate the weak ptrs |
+ // so that task does not execute when we're not expecting it. |
+ weak_factory_.InvalidateWeakPtrs(); |
+ } |
+ |
+ int64_t delay_us = deadline().Subtract(clock_->Now()).ToMicroseconds(); |
+ if (delay_us < 0) { |
+ delay_us = 0; |
+ } |
+ task_runner_->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&QuicChromeAlarm::OnAlarm, weak_factory_.GetWeakPtr()), |
+ base::TimeDelta::FromMicroseconds(delay_us)); |
+ task_deadline_ = deadline(); |
+ } |
+ |
+ void CancelImpl() override { |
+ DCHECK(!deadline().IsInitialized()); |
+ // Since tasks can not be un-posted, OnAlarm will be invoked which |
+ // will notice that deadline is not Initialized and will do nothing. |
+ } |
+ |
+ private: |
+ void OnAlarm() { |
+ DCHECK(task_deadline_.IsInitialized()); |
+ task_deadline_ = QuicTime::Zero(); |
+ // The alarm may have been cancelled. |
+ if (!deadline().IsInitialized()) { |
+ return; |
+ } |
+ |
+ // The alarm may have been re-set to a later time. |
+ if (clock_->Now() < deadline()) { |
+ SetImpl(); |
+ return; |
+ } |
+ |
+ Fire(); |
+ } |
+ |
+ const QuicClock* clock_; |
+ base::TaskRunner* task_runner_; |
+ // If a task has been posted to the message loop, this is the time it |
+ // was scheduled to fire. Tracking this allows us to avoid posting a |
+ // new tast if the new deadline is in the future, but permits us to |
+ // post a new task when the new deadline now earlier than when |
+ // previously posted. |
+ QuicTime task_deadline_; |
+ base::WeakPtrFactory<QuicChromeAlarm> weak_factory_; |
+}; |
+ |
+} // namespace |
+ |
+QuicChromiumAlarmFactory::QuicChromiumAlarmFactory( |
+ base::TaskRunner* task_runner, |
+ const QuicClock* clock) |
+ : task_runner_(task_runner), clock_(clock), weak_factory_(this) {} |
+ |
+QuicChromiumAlarmFactory::~QuicChromiumAlarmFactory() {} |
+ |
+QuicArenaScopedPtr<QuicAlarm> QuicChromiumAlarmFactory::CreateAlarm( |
+ QuicArenaScopedPtr<QuicAlarm::Delegate> delegate, |
+ QuicConnectionArena* arena) { |
+ if (arena != nullptr) { |
+ return arena->New<QuicChromeAlarm>(clock_, task_runner_, |
+ std::move(delegate)); |
+ } else { |
+ return QuicArenaScopedPtr<QuicAlarm>( |
+ new QuicChromeAlarm(clock_, task_runner_, std::move(delegate))); |
+ } |
+} |
+ |
+QuicAlarm* QuicChromiumAlarmFactory::CreateAlarm( |
+ QuicAlarm::Delegate* delegate) { |
+ return new QuicChromeAlarm(clock_, task_runner_, |
+ QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate)); |
+} |
+ |
+} // namespace net |