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