• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_SRC_CORE_LIB_IOMGR_TIMER_H
20 #define GRPC_SRC_CORE_LIB_IOMGR_TIMER_H
21 
22 #include <grpc/event_engine/event_engine.h>
23 #include <grpc/support/port_platform.h>
24 #include <grpc/support/time.h>
25 
26 #include <cstdint>
27 
28 #include "src/core/lib/iomgr/exec_ctx.h"
29 #include "src/core/lib/iomgr/iomgr.h"
30 #include "src/core/lib/iomgr/port.h"
31 
32 typedef struct grpc_timer {
33   int64_t deadline;
34   // Uninitialized if not using heap, or INVALID_HEAP_INDEX if not in heap.
35   uint32_t heap_index;
36   bool pending;
37   struct grpc_timer* next;
38   struct grpc_timer* prev;
39   grpc_closure* closure;
40 #ifndef NDEBUG
41   struct grpc_timer* hash_table_next;
42 #endif
43 
44   // Optional field used by custom timers
45   union {
46     void* custom_timer;
47     grpc_event_engine::experimental::EventEngine::TaskHandle ee_task_handle;
48   };
49 } grpc_timer;
50 
51 static_assert(std::is_trivial<grpc_timer>::value,
52               "grpc_timer is expected to be a trivial type");
53 
54 typedef enum {
55   GRPC_TIMERS_NOT_CHECKED,
56   GRPC_TIMERS_CHECKED_AND_EMPTY,
57   GRPC_TIMERS_FIRED,
58 } grpc_timer_check_result;
59 
60 typedef struct grpc_timer_vtable {
61   void (*init)(grpc_timer* timer, grpc_core::Timestamp, grpc_closure* closure);
62   void (*cancel)(grpc_timer* timer);
63 
64   // Internal API
65   grpc_timer_check_result (*check)(grpc_core::Timestamp* next);
66   void (*list_init)();
67   void (*list_shutdown)(void);
68   void (*consume_kick)(void);
69 } grpc_timer_vtable;
70 
71 // Initialize *timer. When expired or canceled, closure will be called with
72 // error set to indicate if it expired (absl::OkStatus()) or was canceled
73 // (absl::CancelledError()). *closure is guaranteed to be called exactly once,
74 // and application code should check the error to determine how it was invoked.
75 // The application callback is also responsible for maintaining information
76 // about when to free up any user-level state. Behavior is undefined for a
77 // deadline of grpc_core::Timestamp::InfFuture().
78 void grpc_timer_init(grpc_timer* timer, grpc_core::Timestamp deadline,
79                      grpc_closure* closure);
80 
81 // Initialize *timer without setting it. This can later be passed through
82 // the regular init or cancel
83 void grpc_timer_init_unset(grpc_timer* timer);
84 
85 // Note that there is no timer destroy function. This is because the
86 // timer is a one-time occurrence with a guarantee that the callback will
87 // be called exactly once, either at expiration or cancellation. Thus, all
88 // the internal timer event management state is destroyed just before
89 // that callback is invoked. If the user has additional state associated with
90 // the timer, the user is responsible for determining when it is safe to
91 // destroy that state.
92 
93 // Cancel an *timer.
94 // There are three cases:
95 // 1. We normally cancel the timer
96 // 2. The timer has already run
97 // 3. We can't cancel the timer because it is "in flight".
98 
99 // In all of these cases, the cancellation is still considered successful.
100 // They are essentially distinguished in that the timer_cb will be run
101 // exactly once from either the cancellation (with error absl::CancelledError())
102 // or from the activation (with error absl::OkStatus()).
103 
104 // Note carefully that the callback function MAY occur in the same callstack
105 // as grpc_timer_cancel. It's expected that most timers will be cancelled (their
106 // primary use is to implement deadlines), and so this code is optimized such
107 // that cancellation costs as little as possible. Making callbacks run inline
108 // matches this aim.
109 
110 // Requires: cancel() must happen after init() on a given timer
111 void grpc_timer_cancel(grpc_timer* timer);
112 
113 // iomgr internal api for dealing with timers
114 
115 // Check for timers to be run, and run them.
116 // Return true if timer callbacks were executed.
117 // If next is non-null, TRY to update *next with the next running timer
118 // IF that timer occurs before *next current value.
119 // *next is never guaranteed to be updated on any given execution; however,
120 // with high probability at least one thread in the system will see an update
121 // at any time slice.
122 grpc_timer_check_result grpc_timer_check(grpc_core::Timestamp* next);
123 void grpc_timer_list_init();
124 void grpc_timer_list_shutdown();
125 
126 // Consume a kick issued by grpc_kick_poller
127 void grpc_timer_consume_kick(void);
128 
129 // the following must be implemented by each iomgr implementation
130 void grpc_kick_poller(void);
131 
132 // Sets the timer implementation
133 void grpc_set_timer_impl(grpc_timer_vtable* vtable);
134 
135 #endif  // GRPC_SRC_CORE_LIB_IOMGR_TIMER_H
136