event_engine/iomgr_engine/timer.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPC_CORE_LIB_EVENT_ENGINE_IOMGR_ENGINE_TIMER_H
20 #define GRPC_CORE_LIB_EVENT_ENGINE_IOMGR_ENGINE_TIMER_H
21 
23 
24 #include <stddef.h>
25 
26 #include <atomic>
27 #include <cstdint>
28 #include <memory>
29 #include <vector>
30 
31 #include "absl/base/thread_annotations.h"
32 #include "absl/types/optional.h"
33 
35 
40 
41 namespace grpc_event_engine {
42 namespace iomgr_engine {
43 
44 struct Timer {
46  // kInvalidHeapIndex if not in heap.
47  size_t heap_index;
48  bool pending;
49  struct Timer* next;
50  struct Timer* prev;
52 #ifndef NDEBUG
54 #endif
55 
57 };
58 
59 // Dependency injection: allow tests and/or TimerManager to inject
60 // their own implementations of Now, Kick.
62  public:
63  // Return the current timestamp.
64  // Abstracted so that tests can be run deterministically.
65  virtual grpc_core::Timestamp Now() = 0;
66  // Wake up a thread to check for timers.
67  virtual void Kick() = 0;
68 
69  protected:
70  ~TimerListHost() = default;
71 };
72 
73 class TimerList {
74  public:
75  explicit TimerList(TimerListHost* host);
76 
77  TimerList(const TimerList&) = delete;
78  TimerList& operator=(const TimerList&) = delete;
79 
80  /* Initialize *timer. When expired or canceled, closure will be called with
81  error set to indicate if it expired (GRPC_ERROR_NONE) or was canceled
82  (GRPC_ERROR_CANCELLED). *closure is guaranteed to be called exactly once, and
83  application code should check the error to determine how it was invoked. The
84  application callback is also responsible for maintaining information about
85  when to free up any user-level state. Behavior is undefined for a deadline of
86  grpc_core::Timestamp::InfFuture(). */
87  void TimerInit(Timer* timer, grpc_core::Timestamp deadline,
89 
90  /* Note that there is no timer destroy function. This is because the
91  timer is a one-time occurrence with a guarantee that the callback will
92  be called exactly once, either at expiration or cancellation. Thus, all
93  the internal timer event management state is destroyed just before
94  that callback is invoked. If the user has additional state associated with
95  the timer, the user is responsible for determining when it is safe to
96  destroy that state. */
97 
98  /* Cancel an *timer.
99  There are three cases:
100  1. We normally cancel the timer
101  2. The timer has already run
102  3. We can't cancel the timer because it is "in flight".
103 
104  In all of these cases, the cancellation is still considered successful.
105  They are essentially distinguished in that the timer_cb will be run
106  exactly once from either the cancellation (with error GRPC_ERROR_CANCELLED)
107  or from the activation (with error GRPC_ERROR_NONE).
108 
109  Note carefully that the callback function MAY occur in the same callstack
110  as grpc_timer_cancel. It's expected that most timers will be cancelled
111  (their primary use is to implement deadlines), and so this code is
112  optimized such that cancellation costs as little as possible. Making
113  callbacks run inline matches this aim.
114 
115  Requires: cancel() must happen after init() on a given timer */
117 
118  /* iomgr internal api for dealing with timers */
119 
120  /* Check for timers to be run, and return them.
121  Return nullopt if timers could not be checked due to contention with
122  another thread checking.
123  Return a vector of closures that *must* be run otherwise.
124  If next is non-null, TRY to update *next with the next running timer
125  IF that timer occurs before *next current value.
126  *next is never guaranteed to be updated on any given execution; however,
127  with high probability at least one thread in the system will see an update
128  at any time slice. */
131 
132  private:
133  /* A "timer shard". Contains a 'heap' and a 'list' of timers. All timers with
134  * deadlines earlier than 'queue_deadline_cap' are maintained in the heap and
135  * others are maintained in the list (unordered). This helps to keep the
136  * number of elements in the heap low.
137  *
138  * The 'queue_deadline_cap' gets recomputed periodically based on the timer
139  * stats maintained in 'stats' and the relevant timers are then moved from the
140  * 'list' to 'heap'.
141  */
142  struct Shard {
143  Shard();
144 
149  grpc_core::Timestamp* new_min_deadline,
150  std::vector<experimental::EventEngine::Closure*>* out)
152 
155  /* All and only timers with deadlines < this will be in the heap. */
156  grpc_core::Timestamp queue_deadline_cap ABSL_GUARDED_BY(mu);
157  /* The deadline of the next timer due in this shard. */
159  /* Index of this timer_shard in the g_shard_queue. */
160  uint32_t shard_queue_index ABSL_GUARDED_BY(&TimerList::mu_);
161  /* This holds all timers with deadlines < queue_deadline_cap. Timers in this
162  list have the top bit of their deadline set to 0. */
164  /* This holds timers whose deadline is >= queue_deadline_cap. */
165  Timer list ABSL_GUARDED_BY(mu);
166  };
167 
168  void SwapAdjacentShardsInQueue(uint32_t first_shard_queue_index)
171  std::vector<experimental::EventEngine::Closure*> FindExpiredTimers(
173 
175  const size_t num_shards_;
177  /* The deadline of the next timer due across all timer shards */
178  std::atomic<uint64_t> min_timer_;
179  /* Allow only one FindExpiredTimers at once (used as a TryLock, protects no
180  * fields but ensures limits on concurrency) */
182  /* Array of timer shards. Whenever a timer (Timer *) is added, its address
183  * is hashed to select the timer shard to add the timer to */
184  const std::unique_ptr<Shard[]> shards_;
185  /* Maintains a sorted list of timer shards (sorted by their min_deadline, i.e
186  * the deadline of the next timer in each shard). */
187  const std::unique_ptr<Shard*[]> shard_queue_ ABSL_GUARDED_BY(mu_);
188 };
189 
190 } // namespace iomgr_engine
191 } // namespace grpc_event_engine
192 
193 #endif /* GRPC_CORE_LIB_EVENT_ENGINE_IOMGR_ENGINE_TIMER_H */
grpc_event_engine::iomgr_engine::TimerList::Shard::ABSL_GUARDED_BY
TimeAveragedStats stats ABSL_GUARDED_BY(mu)
grpc_event_engine::iomgr_engine::Timer::deadline
int64_t deadline
Definition: event_engine/iomgr_engine/timer.h:45
grpc_event_engine::iomgr_engine::Timer::task_handle
grpc_event_engine::experimental::EventEngine::TaskHandle task_handle
Definition: event_engine/iomgr_engine/timer.h:56
grpc_event_engine::iomgr_engine::TimerList::num_shards_
const size_t num_shards_
Definition: event_engine/iomgr_engine/timer.h:175
grpc_event_engine::iomgr_engine::TimerHeap
Definition: event_engine/iomgr_engine/timer_heap.h:32
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
now
static double now(void)
Definition: test/core/fling/client.cc:130
grpc_event_engine::iomgr_engine::TimerList::Shard
Definition: event_engine/iomgr_engine/timer.h:142
grpc_event_engine::iomgr_engine::Timer::next
struct Timer * next
Definition: event_engine/iomgr_engine/timer.h:49
grpc_event_engine::iomgr_engine::TimerList::TimerCheck
absl::optional< std::vector< experimental::EventEngine::Closure * > > TimerCheck(grpc_core::Timestamp *next)
Definition: event_engine/iomgr_engine/timer.cc:286
grpc_event_engine::iomgr_engine::TimeAveragedStats
Definition: event_engine/iomgr_engine/time_averaged_stats.h:30
grpc_event_engine::iomgr_engine::TimerList::Shard::PopOne
Timer * PopOne(grpc_core::Timestamp now) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu)
Definition: event_engine/iomgr_engine/timer.cc:213
grpc_event_engine::iomgr_engine::TimerListHost::Kick
virtual void Kick()=0
event_engine.h
grpc_core::Timestamp
Definition: src/core/lib/gprpp/time.h:62
grpc_event_engine::iomgr_engine::TimerList::mu_
grpc_core::Mutex mu_
Definition: event_engine/iomgr_engine/timer.h:176
grpc_event_engine::iomgr_engine::Timer::heap_index
size_t heap_index
Definition: event_engine/iomgr_engine/timer.h:47
grpc_event_engine::experimental::EventEngine::TaskHandle
Definition: event_engine.h:102
grpc_event_engine::iomgr_engine::TimerList::TimerList
TimerList(TimerListHost *host)
Definition: event_engine/iomgr_engine/timer.cc:52
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
time_averaged_stats.h
grpc_event_engine::iomgr_engine::TimerList::operator=
TimerList & operator=(const TimerList &)=delete
grpc_event_engine::iomgr_engine::TimerList::ABSL_GUARDED_BY
const std::unique_ptr< Shard *[]> shard_queue_ ABSL_GUARDED_BY(mu_)
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
grpc_event_engine::iomgr_engine::TimerList
Definition: event_engine/iomgr_engine/timer.h:73
grpc_event_engine::iomgr_engine::TimerList::Shard::PopTimers
void PopTimers(grpc_core::Timestamp now, grpc_core::Timestamp *new_min_deadline, std::vector< experimental::EventEngine::Closure * > *out) ABSL_LOCKS_EXCLUDED(mu)
Definition: event_engine/iomgr_engine/timer.cc:231
ABSL_EXCLUSIVE_LOCKS_REQUIRED
#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: abseil-cpp/absl/base/thread_annotations.h:145
grpc_event_engine::iomgr_engine::Timer::pending
bool pending
Definition: event_engine/iomgr_engine/timer.h:48
gen_stats_data.stats
list stats
Definition: gen_stats_data.py:58
absl::optional
Definition: abseil-cpp/absl/types/internal/optional.h:61
grpc_event_engine::iomgr_engine::TimerList::Shard::ComputeMinDeadline
grpc_core::Timestamp ComputeMinDeadline() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu)
Definition: event_engine/iomgr_engine/timer.cc:43
grpc_event_engine::iomgr_engine::Timer::hash_table_next
struct Timer * hash_table_next
Definition: event_engine/iomgr_engine/timer.h:53
grpc_event_engine::iomgr_engine::TimerList::host_
TimerListHost *const host_
Definition: event_engine/iomgr_engine/timer.h:174
time.h
grpc_event_engine::iomgr_engine::TimerList::min_timer_
std::atomic< uint64_t > min_timer_
Definition: event_engine/iomgr_engine/timer.h:178
grpc_event_engine::iomgr_engine::TimerList::TimerCancel
bool TimerCancel(Timer *timer) GRPC_MUST_USE_RESULT
Definition: event_engine/iomgr_engine/timer.cc:164
grpc_event_engine::iomgr_engine::TimerList::shards_
const std::unique_ptr< Shard[]> shards_
Definition: event_engine/iomgr_engine/timer.h:184
grpc_event_engine::iomgr_engine::TimerList::NoteDeadlineChange
void NoteDeadlineChange(Shard *shard) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_)
Definition: event_engine/iomgr_engine/timer.cc:96
grpc_event_engine::iomgr_engine::TimerListHost::~TimerListHost
~TimerListHost()=default
grpc_event_engine::iomgr_engine::Timer
Definition: event_engine/iomgr_engine/timer.h:44
grpc_event_engine::iomgr_engine::Timer::prev
struct Timer * prev
Definition: event_engine/iomgr_engine/timer.h:50
grpc_event_engine::iomgr_engine::Timer::closure
experimental::EventEngine::Closure * closure
Definition: event_engine/iomgr_engine/timer.h:51
grpc_event_engine::iomgr_engine::TimerList::TimerInit
void TimerInit(Timer *timer, grpc_core::Timestamp deadline, experimental::EventEngine::Closure *closure)
Definition: event_engine/iomgr_engine/timer.cc:109
grpc_event_engine::iomgr_engine::TimerList::Shard::mu
grpc_core::Mutex mu
Definition: event_engine/iomgr_engine/timer.h:153
grpc_core::Mutex
Definition: src/core/lib/gprpp/sync.h:61
grpc_event_engine::experimental::EventEngine::Closure
Definition: event_engine.h:87
GRPC_MUST_USE_RESULT
#define GRPC_MUST_USE_RESULT
Definition: impl/codegen/port_platform.h:584
grpc_event_engine::iomgr_engine::TimerList::Shard::Shard
Shard()
Definition: event_engine/iomgr_engine/timer.cc:50
grpc_event_engine::iomgr_engine::TimerList::Shard::RefillHeap
bool RefillHeap(grpc_core::Timestamp now) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu)
Definition: event_engine/iomgr_engine/timer.cc:185
ABSL_LOCKS_EXCLUDED
#define ABSL_LOCKS_EXCLUDED(...)
Definition: abseil-cpp/absl/base/thread_annotations.h:163
next
AllocList * next[kMaxLevel]
Definition: abseil-cpp/absl/base/internal/low_level_alloc.cc:100
grpc_event_engine
Definition: endpoint_config.h:24
timer_heap.h
grpc_event_engine::iomgr_engine::TimerList::SwapAdjacentShardsInQueue
void SwapAdjacentShardsInQueue(uint32_t first_shard_queue_index) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_)
Definition: event_engine/iomgr_engine/timer.cc:84
closure
Definition: proxy.cc:59
grpc_event_engine::iomgr_engine::TimerListHost::Now
virtual grpc_core::Timestamp Now()=0
grpc_event_engine::iomgr_engine::TimerList::FindExpiredTimers
std::vector< experimental::EventEngine::Closure * > FindExpiredTimers(grpc_core::Timestamp now, grpc_core::Timestamp *next)
Definition: event_engine/iomgr_engine/timer.cc:241
grpc_event_engine::iomgr_engine::TimerList::checker_mu_
grpc_core::Mutex checker_mu_
Definition: event_engine/iomgr_engine/timer.h:181
heap
Definition: heap-inl.h:40
sync.h
timer
static uv_timer_t timer
Definition: test-callback-stack.c:34
grpc_event_engine::iomgr_engine::TimerListHost
Definition: event_engine/iomgr_engine/timer.h:61
port_platform.h


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:38