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