Files

317 lines
11 KiB
C
Raw Permalink Normal View History

2026-08-03 18:42:47 +08:00
#ifndef AWS_IO_EVENT_LOOP_H
#define AWS_IO_EVENT_LOOP_H
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/io/io.h>
AWS_PUSH_SANE_WARNING_LEVEL
struct aws_event_loop;
struct aws_event_loop_group;
struct aws_event_loop_options;
struct aws_shutdown_callback_options;
struct aws_task;
/**
* @internal
*/
typedef void(aws_event_loop_on_event_fn)(
struct aws_event_loop *event_loop,
struct aws_io_handle *handle,
int events,
void *user_data);
/**
* @internal
*/
struct aws_event_loop_vtable {
void (*start_destroy)(struct aws_event_loop *event_loop);
void (*complete_destroy)(struct aws_event_loop *event_loop);
int (*run)(struct aws_event_loop *event_loop);
int (*stop)(struct aws_event_loop *event_loop);
int (*wait_for_stop_completion)(struct aws_event_loop *event_loop);
void (*schedule_task_now)(struct aws_event_loop *event_loop, struct aws_task *task);
void (*schedule_task_now_serialized)(struct aws_event_loop *event_loop, struct aws_task *task);
void (*schedule_task_future)(struct aws_event_loop *event_loop, struct aws_task *task, uint64_t run_at_nanos);
void (*cancel_task)(struct aws_event_loop *event_loop, struct aws_task *task);
int (*connect_to_io_completion_port)(struct aws_event_loop *event_loop, struct aws_io_handle *handle);
int (*subscribe_to_io_events)(
struct aws_event_loop *event_loop,
struct aws_io_handle *handle,
int events,
aws_event_loop_on_event_fn *on_event,
void *user_data);
int (*unsubscribe_from_io_events)(struct aws_event_loop *event_loop, struct aws_io_handle *handle);
void (*free_io_event_resources)(void *user_data);
bool (*is_on_callers_thread)(struct aws_event_loop *event_loop);
};
/**
* Event Loop Type. If set to `AWS_EVENT_LOOP_PLATFORM_DEFAULT`, the event loop will automatically use the platform’s
* default.
*
* Default Event Loop Type
* Linux | AWS_EVENT_LOOP_EPOLL
* Windows | AWS_EVENT_LOOP_IOCP
* BSD Variants| AWS_EVENT_LOOP_KQUEUE
* macOS | AWS_EVENT_LOOP_KQUEUE
* iOS | AWS_EVENT_LOOP_DISPATCH_QUEUE
*/
enum aws_event_loop_type {
AWS_EVENT_LOOP_PLATFORM_DEFAULT = 0,
AWS_EVENT_LOOP_EPOLL,
AWS_EVENT_LOOP_IOCP,
AWS_EVENT_LOOP_KQUEUE,
AWS_EVENT_LOOP_DISPATCH_QUEUE,
};
/**
* Event loop group configuration options
*/
struct aws_event_loop_group_options {
/**
* How many event loops that event loop group should contain. For most group types, this implies
* the creation and management of an analagous amount of managed threads
*/
uint16_t loop_count;
/**
* Event loop type. If the event loop type is set to AWS_EVENT_LOOP_PLATFORM_DEFAULT, the
* creation function will automatically use the platform’s default event loop type.
*/
enum aws_event_loop_type type;
/**
* Optional callback to invoke when the event loop group finishes destruction.
*/
const struct aws_shutdown_callback_options *shutdown_options;
/**
* Optional configuration to control how the event loop group's threads bind to CPU groups
*/
const uint16_t *cpu_group;
/**
* Override for the clock function that event loops should use. Defaults to the system's high resolution
* timer.
*
* Do not bind this value to managed code; it is only used in timing-sensitive tests.
*/
aws_io_clock_fn *clock_override;
};
AWS_EXTERN_C_BEGIN
/**
* The event loop will schedule the task and run it on the event loop thread as soon as possible.
* Note that cancelled tasks may execute outside the event loop thread.
* This function may be called from outside or inside the event loop thread.
*
* The task should not be cleaned up or modified until its function is executed.
*/
AWS_IO_API
void aws_event_loop_schedule_task_now(struct aws_event_loop *event_loop, struct aws_task *task);
/**
* Variant of aws_event_loop_schedule_task_now that forces all tasks to go through the cross thread task queue,
* guaranteeing that order-of-submission is order-of-execution. If you need this guarantee, you must use this
* function; the base function contains short-circuiting logic that breaks ordering invariants. Beyond that, all
* properties of aws_event_loop_schedule_task_now apply to this function as well.
*
* Serialization guarantee does not apply to task cancellation (which can occur out-of-order or even out-of-thread in
* certain cases).
*/
AWS_IO_API
void aws_event_loop_schedule_task_now_serialized(struct aws_event_loop *event_loop, struct aws_task *task);
/**
* The event loop will schedule the task and run it at the specified time.
* Use aws_event_loop_current_clock_time() to query the current time in nanoseconds.
* Note that cancelled tasks may execute outside the event loop thread.
* This function may be called from outside or inside the event loop thread.
*
* The task should not be cleaned up or modified until its function is executed.
*/
AWS_IO_API
void aws_event_loop_schedule_task_future(
struct aws_event_loop *event_loop,
struct aws_task *task,
uint64_t run_at_nanos);
/**
* Cancels task.
* This function must be called from the event loop's thread, and is only guaranteed
* to work properly on tasks scheduled from within the event loop's thread.
* The task will be executed with the AWS_TASK_STATUS_CANCELED status inside this call.
*/
AWS_IO_API
void aws_event_loop_cancel_task(struct aws_event_loop *event_loop, struct aws_task *task);
/**
* Returns true if the event loop's thread is the same thread that called this function, otherwise false.
*/
AWS_IO_API
bool aws_event_loop_thread_is_callers_thread(struct aws_event_loop *event_loop);
/**
* Gets the current timestamp for the event loop's clock, in nanoseconds. This function is thread-safe.
*/
AWS_IO_API
int aws_event_loop_current_clock_time(const struct aws_event_loop *event_loop, uint64_t *time_nanos);
/**
* Creation function for event loop groups.
*/
AWS_IO_API
struct aws_event_loop_group *aws_event_loop_group_new(
struct aws_allocator *allocator,
const struct aws_event_loop_group_options *options);
/**
* Increments the reference count on the event loop group, allowing the caller to take a reference to it.
*
* Returns the same event loop group passed in.
*/
AWS_IO_API
struct aws_event_loop_group *aws_event_loop_group_acquire(struct aws_event_loop_group *el_group);
/**
* Decrements an event loop group's ref count. When the ref count drops to zero, the event loop group will be
* destroyed.
*/
AWS_IO_API
void aws_event_loop_group_release(struct aws_event_loop_group *el_group);
/**
* Increments the reference count on the event loop group from event loop, allowing the caller to take a reference to
* it.
*
* Returns the base event loop group of the event loop, or null if the event loop does not belong to a group.
*/
AWS_IO_API
struct aws_event_loop_group *aws_event_loop_group_acquire_from_event_loop(struct aws_event_loop *event_loop);
/**
* Decrements the ref count of the event loop's base event loop group. When the ref count drops to zero, the event loop
* group will be destroyed.
*/
AWS_IO_API
void aws_event_loop_group_release_from_event_loop(struct aws_event_loop *event_loop);
/**
* Returns the event loop at a particular index. If the index is out of bounds, null is returned.
*/
AWS_IO_API
struct aws_event_loop *aws_event_loop_group_get_loop_at(struct aws_event_loop_group *el_group, size_t index);
/**
* Gets the number of event loops managed by an event loop group.
*/
AWS_IO_API
size_t aws_event_loop_group_get_loop_count(const struct aws_event_loop_group *el_group);
/**
* Gets the event loop type used by an event loop group.
*/
AWS_IO_API
enum aws_event_loop_type aws_event_loop_group_get_type(const struct aws_event_loop_group *el_group);
/**
* Fetches the next loop for use. The purpose is to enable load balancing across loops. You should not depend on how
* this load balancing is done as it is subject to change in the future. Currently it uses the "best-of-two" algorithm
* based on the load factor of each loop.
*/
AWS_IO_API
struct aws_event_loop *aws_event_loop_group_get_next_loop(struct aws_event_loop_group *el_group);
/**
* @deprecated - use aws_event_loop_group_new() instead
*/
AWS_IO_API
struct aws_event_loop_group *aws_event_loop_group_new_default(
struct aws_allocator *alloc,
uint16_t max_threads,
const struct aws_shutdown_callback_options *shutdown_options);
/**
* @deprecated - use aws_event_loop_group_new() instead
*/
AWS_IO_API
struct aws_event_loop_group *aws_event_loop_group_new_default_pinned_to_cpu_group(
struct aws_allocator *alloc,
uint16_t max_threads,
uint16_t cpu_group,
const struct aws_shutdown_callback_options *shutdown_options);
/**
* @internal - Don't use outside of testing.
*
* Returns the opaque internal user data of an event loop. Can be cast into a specific implementation by
* privileged consumers.
*/
AWS_IO_API
void *aws_event_loop_get_impl(struct aws_event_loop *event_loop);
/**
* @internal - Don't use outside of testing.
*
* Initializes the base structure used by all event loop implementations with test-oriented overrides.
*/
AWS_IO_API
struct aws_event_loop *aws_event_loop_new_base(
struct aws_allocator *allocator,
aws_io_clock_fn *clock,
struct aws_event_loop_vtable *vtable,
void *impl);
/**
* @internal - Don't use outside of testing.
*
* Common cleanup code for all implementations.
* This is only called from the *destroy() function of event loop implementations.
*/
AWS_IO_API
void aws_event_loop_clean_up_base(struct aws_event_loop *event_loop);
/**
* @internal - Don't use outside of testing.
*
* Destroys an event loop implementation.
* If the event loop is still in a running state, this function will block waiting on the event loop to shutdown.
* If the event loop is shared by multiple threads then destroy must be called by exactly one thread. All other threads
* must ensure their API calls to the event loop happen-before the call to destroy.
*
* Internally, this calls aws_event_loop_start_destroy() followed by aws_event_loop_complete_destroy()
*/
AWS_IO_API
void aws_event_loop_destroy(struct aws_event_loop *event_loop);
/**
* @internal
*
* Signals an event loop to begin its destruction process. If an event loop's implementation of this API does anything,
* it must be quick and non-blocking. Most event loop implementations have an empty implementation for this function.
*/
AWS_IO_API
void aws_event_loop_start_destroy(struct aws_event_loop *event_loop);
/**
* @internal
*
* Waits for an event loop to complete its destruction process. aws_event_loop_start_destroy() must have been called
* previously for this function to not deadlock.
*/
AWS_IO_API
void aws_event_loop_complete_destroy(struct aws_event_loop *event_loop);
AWS_EXTERN_C_END
AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_IO_EVENT_LOOP_H */