#ifndef AWS_IO_EVENT_LOOP_H
#define AWS_IO_EVENT_LOOP_H
#include <aws/common/atomics.h>
#include <aws/common/hash_table.h>
#include <aws/common/ref_count.h>
#include <aws/io/io.h>
enum aws_io_event_type {
AWS_IO_EVENT_TYPE_READABLE = 1,
AWS_IO_EVENT_TYPE_WRITABLE = 2,
AWS_IO_EVENT_TYPE_REMOTE_HANG_UP = 4,
AWS_IO_EVENT_TYPE_CLOSED = 8,
AWS_IO_EVENT_TYPE_ERROR = 16,
};
struct aws_event_loop;
struct aws_task;
struct aws_thread_options;
#if AWS_USE_IO_COMPLETION_PORTS
struct aws_overlapped;
typedef void(aws_event_loop_on_completion_fn)(
struct aws_event_loop *event_loop,
struct aws_overlapped *overlapped,
int status_code,
size_t num_bytes_transferred);
struct aws_win32_OVERLAPPED {
uintptr_t Internal;
uintptr_t InternalHigh;
union {
struct {
uint32_t Offset;
uint32_t OffsetHigh;
} s;
void *Pointer;
} u;
void *hEvent;
};
struct aws_overlapped {
struct aws_win32_OVERLAPPED overlapped;
aws_event_loop_on_completion_fn *on_completion;
void *user_data;
};
#else
typedef void(aws_event_loop_on_event_fn)(
struct aws_event_loop *event_loop,
struct aws_io_handle *handle,
int events,
void *user_data);
#endif
struct aws_event_loop_vtable {
void (*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_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);
#if AWS_USE_IO_COMPLETION_PORTS
int (*connect_to_io_completion_port)(struct aws_event_loop *event_loop, struct aws_io_handle *handle);
#else
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);
#endif
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);
};
struct aws_event_loop {
struct aws_event_loop_vtable *vtable;
struct aws_allocator *alloc;
aws_io_clock_fn *clock;
struct aws_hash_table local_data;
struct aws_atomic_var current_load_factor;
uint64_t latest_tick_start;
size_t current_tick_latency_sum;
struct aws_atomic_var next_flush_time;
void *impl_data;
};
struct aws_event_loop_local_object;
typedef void(aws_event_loop_on_local_object_removed_fn)(struct aws_event_loop_local_object *);
struct aws_event_loop_local_object {
const void *key;
void *object;
aws_event_loop_on_local_object_removed_fn *on_object_removed;
};
struct aws_event_loop_options {
aws_io_clock_fn *clock;
struct aws_thread_options *thread_options;
};
typedef struct aws_event_loop *(aws_new_event_loop_fn)(
struct aws_allocator *alloc,
const struct aws_event_loop_options *options,
void *new_loop_user_data);
struct aws_event_loop_group {
struct aws_allocator *allocator;
struct aws_array_list event_loops;
struct aws_ref_count ref_count;
struct aws_shutdown_callback_options shutdown_options;
};
AWS_EXTERN_C_BEGIN
#ifdef AWS_USE_IO_COMPLETION_PORTS
AWS_IO_API
void aws_overlapped_init(
struct aws_overlapped *overlapped,
aws_event_loop_on_completion_fn *on_completion,
void *user_data);
AWS_IO_API
void aws_overlapped_reset(struct aws_overlapped *overlapped);
AWS_IO_API
struct _OVERLAPPED *aws_overlapped_to_windows_overlapped(struct aws_overlapped *overlapped);
#endif
AWS_IO_API
struct aws_event_loop *aws_event_loop_new_default(struct aws_allocator *alloc, aws_io_clock_fn *clock);
AWS_IO_API
struct aws_event_loop *aws_event_loop_new_default_with_options(
struct aws_allocator *alloc,
const struct aws_event_loop_options *options);
AWS_IO_API
void aws_event_loop_destroy(struct aws_event_loop *event_loop);
AWS_IO_API
int aws_event_loop_init_base(struct aws_event_loop *event_loop, struct aws_allocator *alloc, aws_io_clock_fn *clock);
AWS_IO_API
void aws_event_loop_clean_up_base(struct aws_event_loop *event_loop);
AWS_IO_API
int aws_event_loop_fetch_local_object(
struct aws_event_loop *event_loop,
void *key,
struct aws_event_loop_local_object *obj);
AWS_IO_API
int aws_event_loop_put_local_object(struct aws_event_loop *event_loop, struct aws_event_loop_local_object *obj);
AWS_IO_API
int aws_event_loop_remove_local_object(
struct aws_event_loop *event_loop,
void *key,
struct aws_event_loop_local_object *removed_obj);
AWS_IO_API
int aws_event_loop_run(struct aws_event_loop *event_loop);
AWS_IO_API
int aws_event_loop_stop(struct aws_event_loop *event_loop);
AWS_IO_API
void aws_event_loop_register_tick_start(struct aws_event_loop *event_loop);
AWS_IO_API
void aws_event_loop_register_tick_end(struct aws_event_loop *event_loop);
AWS_IO_API
size_t aws_event_loop_get_load_factor(struct aws_event_loop *event_loop);
AWS_IO_API
int aws_event_loop_wait_for_stop_completion(struct aws_event_loop *event_loop);
AWS_IO_API
void aws_event_loop_schedule_task_now(struct aws_event_loop *event_loop, struct aws_task *task);
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);
AWS_IO_API
void aws_event_loop_cancel_task(struct aws_event_loop *event_loop, struct aws_task *task);
#if AWS_USE_IO_COMPLETION_PORTS
AWS_IO_API
int aws_event_loop_connect_handle_to_io_completion_port(
struct aws_event_loop *event_loop,
struct aws_io_handle *handle);
#else
AWS_IO_API
int aws_event_loop_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);
#endif
AWS_IO_API
int aws_event_loop_unsubscribe_from_io_events(struct aws_event_loop *event_loop, struct aws_io_handle *handle);
AWS_IO_API
void aws_event_loop_free_io_event_resources(struct aws_event_loop *event_loop, struct aws_io_handle *handle);
AWS_IO_API
bool aws_event_loop_thread_is_callers_thread(struct aws_event_loop *event_loop);
AWS_IO_API
int aws_event_loop_current_clock_time(struct aws_event_loop *event_loop, uint64_t *time_nanos);
AWS_IO_API
struct aws_event_loop_group *aws_event_loop_group_new(
struct aws_allocator *alloc,
aws_io_clock_fn *clock,
uint16_t el_count,
aws_new_event_loop_fn *new_loop_fn,
void *new_loop_user_data,
const struct aws_shutdown_callback_options *shutdown_options);
AWS_IO_API
struct aws_event_loop_group *aws_event_loop_group_new_pinned_to_cpu_group(
struct aws_allocator *alloc,
aws_io_clock_fn *clock,
uint16_t el_count,
uint16_t cpu_group,
aws_new_event_loop_fn *new_loop_fn,
void *new_loop_user_data,
const struct aws_shutdown_callback_options *shutdown_options);
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);
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);
AWS_IO_API
struct aws_event_loop_group *aws_event_loop_group_acquire(struct aws_event_loop_group *el_group);
AWS_IO_API
void aws_event_loop_group_release(struct aws_event_loop_group *el_group);
AWS_IO_API
struct aws_event_loop *aws_event_loop_group_get_loop_at(struct aws_event_loop_group *el_group, size_t index);
AWS_IO_API
size_t aws_event_loop_group_get_loop_count(struct aws_event_loop_group *el_group);
AWS_IO_API
struct aws_event_loop *aws_event_loop_group_get_next_loop(struct aws_event_loop_group *el_group);
AWS_EXTERN_C_END
#endif