blob: 492b8692646eb562f75b0a15bab1ddd981ba70ae [file] [log] [blame]
//
//
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#ifndef GRPC_SRC_CORE_LIB_IOMGR_TIMER_H
#define GRPC_SRC_CORE_LIB_IOMGR_TIMER_H
#include <grpc/support/port_platform.h>
#include <cstdint>
#include <grpc/event_engine/event_engine.h>
#include <grpc/support/time.h>
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/port.h"
typedef struct grpc_timer {
int64_t deadline;
// Uninitialized if not using heap, or INVALID_HEAP_INDEX if not in heap.
uint32_t heap_index;
bool pending;
struct grpc_timer* next;
struct grpc_timer* prev;
grpc_closure* closure;
#ifndef NDEBUG
struct grpc_timer* hash_table_next;
#endif
// Optional field used by custom timers
union {
void* custom_timer;
grpc_event_engine::experimental::EventEngine::TaskHandle ee_task_handle;
};
} grpc_timer;
static_assert(std::is_trivial<grpc_timer>::value,
"grpc_timer is expected to be a trivial type");
typedef enum {
GRPC_TIMERS_NOT_CHECKED,
GRPC_TIMERS_CHECKED_AND_EMPTY,
GRPC_TIMERS_FIRED,
} grpc_timer_check_result;
typedef struct grpc_timer_vtable {
void (*init)(grpc_timer* timer, grpc_core::Timestamp, grpc_closure* closure);
void (*cancel)(grpc_timer* timer);
// Internal API
grpc_timer_check_result (*check)(grpc_core::Timestamp* next);
void (*list_init)();
void (*list_shutdown)(void);
void (*consume_kick)(void);
} grpc_timer_vtable;
// Initialize *timer. When expired or canceled, closure will be called with
// error set to indicate if it expired (absl::OkStatus()) or was canceled
// (absl::CancelledError()). *closure is guaranteed to be called exactly once,
// and application code should check the error to determine how it was invoked.
// The application callback is also responsible for maintaining information
// about when to free up any user-level state. Behavior is undefined for a
// deadline of grpc_core::Timestamp::InfFuture().
void grpc_timer_init(grpc_timer* timer, grpc_core::Timestamp deadline,
grpc_closure* closure);
// Initialize *timer without setting it. This can later be passed through
// the regular init or cancel
void grpc_timer_init_unset(grpc_timer* timer);
// Note that there is no timer destroy function. This is because the
// timer is a one-time occurrence with a guarantee that the callback will
// be called exactly once, either at expiration or cancellation. Thus, all
// the internal timer event management state is destroyed just before
// that callback is invoked. If the user has additional state associated with
// the timer, the user is responsible for determining when it is safe to
// destroy that state.
// Cancel an *timer.
// There are three cases:
// 1. We normally cancel the timer
// 2. The timer has already run
// 3. We can't cancel the timer because it is "in flight".
// In all of these cases, the cancellation is still considered successful.
// They are essentially distinguished in that the timer_cb will be run
// exactly once from either the cancellation (with error absl::CancelledError())
// or from the activation (with error absl::OkStatus()).
// Note carefully that the callback function MAY occur in the same callstack
// as grpc_timer_cancel. It's expected that most timers will be cancelled (their
// primary use is to implement deadlines), and so this code is optimized such
// that cancellation costs as little as possible. Making callbacks run inline
// matches this aim.
// Requires: cancel() must happen after init() on a given timer
void grpc_timer_cancel(grpc_timer* timer);
// iomgr internal api for dealing with timers
// Check for timers to be run, and run them.
// Return true if timer callbacks were executed.
// If next is non-null, TRY to update *next with the next running timer
// IF that timer occurs before *next current value.
// *next is never guaranteed to be updated on any given execution; however,
// with high probability at least one thread in the system will see an update
// at any time slice.
grpc_timer_check_result grpc_timer_check(grpc_core::Timestamp* next);
void grpc_timer_list_init();
void grpc_timer_list_shutdown();
// Consume a kick issued by grpc_kick_poller
void grpc_timer_consume_kick(void);
// the following must be implemented by each iomgr implementation
void grpc_kick_poller(void);
// Sets the timer implementation
void grpc_set_timer_impl(grpc_timer_vtable* vtable);
#endif // GRPC_SRC_CORE_LIB_IOMGR_TIMER_H