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