1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "quiche/quic/core/quic_alarm.h" 6 7 #include <atomic> 8 9 #include "quiche/quic/platform/api/quic_bug_tracker.h" 10 #include "quiche/quic/platform/api/quic_flag_utils.h" 11 #include "quiche/quic/platform/api/quic_flags.h" 12 #include "quiche/quic/platform/api/quic_stack_trace.h" 13 14 namespace quic { 15 QuicAlarm(QuicArenaScopedPtr<Delegate> delegate)16QuicAlarm::QuicAlarm(QuicArenaScopedPtr<Delegate> delegate) 17 : delegate_(std::move(delegate)), deadline_(QuicTime::Zero()) {} 18 ~QuicAlarm()19QuicAlarm::~QuicAlarm() { 20 if (IsSet()) { 21 QUIC_CODE_COUNT(quic_alarm_not_cancelled_in_dtor); 22 } 23 } 24 Set(QuicTime new_deadline)25void QuicAlarm::Set(QuicTime new_deadline) { 26 QUICHE_DCHECK(!IsSet()); 27 QUICHE_DCHECK(new_deadline.IsInitialized()); 28 29 if (IsPermanentlyCancelled()) { 30 QUIC_BUG(quic_alarm_illegal_set) 31 << "Set called after alarm is permanently cancelled. new_deadline:" 32 << new_deadline; 33 return; 34 } 35 36 deadline_ = new_deadline; 37 SetImpl(); 38 } 39 CancelInternal(bool permanent)40void QuicAlarm::CancelInternal(bool permanent) { 41 if (IsSet()) { 42 deadline_ = QuicTime::Zero(); 43 CancelImpl(); 44 } 45 46 if (permanent) { 47 delegate_.reset(); 48 } 49 } 50 IsPermanentlyCancelled() const51bool QuicAlarm::IsPermanentlyCancelled() const { return delegate_ == nullptr; } 52 Update(QuicTime new_deadline,QuicTime::Delta granularity)53void QuicAlarm::Update(QuicTime new_deadline, QuicTime::Delta granularity) { 54 if (IsPermanentlyCancelled()) { 55 QUIC_BUG(quic_alarm_illegal_update) 56 << "Update called after alarm is permanently cancelled. new_deadline:" 57 << new_deadline << ", granularity:" << granularity; 58 return; 59 } 60 61 if (!new_deadline.IsInitialized()) { 62 Cancel(); 63 return; 64 } 65 if (std::abs((new_deadline - deadline_).ToMicroseconds()) < 66 granularity.ToMicroseconds()) { 67 return; 68 } 69 const bool was_set = IsSet(); 70 deadline_ = new_deadline; 71 if (was_set) { 72 UpdateImpl(); 73 } else { 74 SetImpl(); 75 } 76 } 77 IsSet() const78bool QuicAlarm::IsSet() const { return deadline_.IsInitialized(); } 79 Fire()80void QuicAlarm::Fire() { 81 if (!IsSet()) { 82 return; 83 } 84 85 deadline_ = QuicTime::Zero(); 86 if (!IsPermanentlyCancelled()) { 87 QuicConnectionContextSwitcher context_switcher( 88 delegate_->GetConnectionContext()); 89 delegate_->OnAlarm(); 90 } 91 } 92 UpdateImpl()93void QuicAlarm::UpdateImpl() { 94 // CancelImpl and SetImpl take the new deadline by way of the deadline_ 95 // member, so save and restore deadline_ before canceling. 96 const QuicTime new_deadline = deadline_; 97 98 deadline_ = QuicTime::Zero(); 99 CancelImpl(); 100 101 deadline_ = new_deadline; 102 SetImpl(); 103 } 104 105 } // namespace quic 106