Skip to content

Commit

Permalink
Dispatch Queue Shutdown Polish (#708)
Browse files Browse the repository at this point in the history
Co-authored-by: Bret Ambrose <[email protected]>
Co-authored-by: Vera Xia <[email protected]>
  • Loading branch information
3 people authored Feb 18, 2025
1 parent 4aba816 commit bd95b21
Show file tree
Hide file tree
Showing 8 changed files with 320 additions and 165 deletions.
26 changes: 23 additions & 3 deletions include/aws/io/event_loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ typedef void(aws_event_loop_on_event_fn)(
* @internal
*/
struct aws_event_loop_vtable {
void (*destroy)(struct aws_event_loop *event_loop);
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);
Expand Down Expand Up @@ -246,15 +247,34 @@ void aws_event_loop_clean_up_base(struct aws_event_loop *event_loop);
/**
* @internal - Don't use outside of testing.
*
* Invokes the destroy() fn for the event loop implementation.
* 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 you do not want this function to block, call aws_event_loop_stop() manually first.
* 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
Expand Down
9 changes: 7 additions & 2 deletions include/aws/testing/io_testing_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ static bool s_testing_loop_is_on_callers_thread(struct aws_event_loop *event_loo
return testing_loop->mock_on_callers_thread;
}

static void s_testing_loop_destroy(struct aws_event_loop *event_loop) {
static void s_testing_loop_start_destroy(struct aws_event_loop *event_loop) {
(void)event_loop;
}

static void s_testing_loop_complete_destroy(struct aws_event_loop *event_loop) {
struct testing_loop *testing_loop = (struct testing_loop *)aws_event_loop_get_impl(event_loop);
struct aws_allocator *allocator = testing_loop->allocator;
aws_task_scheduler_clean_up(&testing_loop->scheduler);
Expand All @@ -67,7 +71,8 @@ static void s_testing_loop_destroy(struct aws_event_loop *event_loop) {
}

static struct aws_event_loop_vtable s_testing_loop_vtable = {
.destroy = s_testing_loop_destroy,
.start_destroy = s_testing_loop_start_destroy,
.complete_destroy = s_testing_loop_complete_destroy,
.is_on_callers_thread = s_testing_loop_is_on_callers_thread,
.run = s_testing_loop_run,
.schedule_task_now = s_testing_loop_schedule_task_now,
Expand Down
12 changes: 9 additions & 3 deletions source/bsd/kqueue_event_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
#include <limits.h>
#include <unistd.h>

static void s_destroy(struct aws_event_loop *event_loop);
static void s_start_destroy(struct aws_event_loop *event_loop);
static void s_complete_destroy(struct aws_event_loop *event_loop);
static int s_run(struct aws_event_loop *event_loop);
static int s_stop(struct aws_event_loop *event_loop);
static int s_wait_for_stop_completion(struct aws_event_loop *event_loop);
Expand Down Expand Up @@ -135,7 +136,8 @@ enum {
};

struct aws_event_loop_vtable s_kqueue_vtable = {
.destroy = s_destroy,
.start_destroy = s_start_destroy,
.complete_destroy = s_complete_destroy,
.run = s_run,
.stop = s_stop,
.wait_for_stop_completion = s_wait_for_stop_completion,
Expand Down Expand Up @@ -313,7 +315,11 @@ struct aws_event_loop *aws_event_loop_new_with_kqueue(
}
#endif // AWS_ENABLE_KQUEUE

static void s_destroy(struct aws_event_loop *event_loop) {
static void s_start_destroy(struct aws_event_loop *event_loop) {
(void)event_loop;
}

static void s_complete_destroy(struct aws_event_loop *event_loop) {
AWS_LOGF_INFO(AWS_LS_IO_EVENT_LOOP, "id=%p: destroying event_loop", (void *)event_loop);
struct kqueue_loop *impl = event_loop->impl_data;

Expand Down
Loading

0 comments on commit bd95b21

Please sign in to comment.