xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_alarm.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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)16 QuicAlarm::QuicAlarm(QuicArenaScopedPtr<Delegate> delegate)
17     : delegate_(std::move(delegate)), deadline_(QuicTime::Zero()) {}
18 
~QuicAlarm()19 QuicAlarm::~QuicAlarm() {
20   if (IsSet()) {
21     QUIC_CODE_COUNT(quic_alarm_not_cancelled_in_dtor);
22   }
23 }
24 
Set(QuicTime new_deadline)25 void 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)40 void 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() const51 bool QuicAlarm::IsPermanentlyCancelled() const { return delegate_ == nullptr; }
52 
Update(QuicTime new_deadline,QuicTime::Delta granularity)53 void 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() const78 bool QuicAlarm::IsSet() const { return deadline_.IsInitialized(); }
79 
Fire()80 void 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()93 void 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