static void as_uv_wakeup(uv_async_t* wakeup) { // Read command pointers from queue. as_event_loop* event_loop = wakeup->data; as_uv_command cmd; pthread_mutex_lock(&event_loop->lock); while (as_queue_pop(&event_loop->queue, &cmd)) { switch (cmd.type) { case AS_UV_PROCESS_COMMAND: as_event_command_execute_in_loop(cmd.ptr); break; case AS_UV_CLOSE_CONNECTION: uv_close((uv_handle_t*)cmd.ptr, as_uv_connection_closed); break; case AS_UV_EXIT_LOOP: as_event_close_loop(event_loop); return; } } pthread_mutex_unlock(&event_loop->lock); }
void as_event_close_loops() { if (! as_event_loops) { return; } pthread_t self = pthread_self(); bool status = true; // Close or send close signal to all event loops. // This will eventually release resources associated with each event loop. for (uint32_t i = 0; i < as_event_loop_size; i++) { as_event_loop* event_loop = &as_event_loops[i]; if (event_loop->thread == self) { // Can close event loop immediately. as_event_close_loop(event_loop); } else { // Queue close command to event loop. if (! as_event_send_close_loop(event_loop)) { as_log_error("Failed to send stop command to event loop"); status = false; } } } // Only join threads if event loops were created internally. // It is not possible to join on externally created event loop threads. if (as_event_threads_created && status) { for (uint32_t i = 0; i < as_event_loop_size; i++) { as_event_loop* event_loop = &as_event_loops[i]; pthread_join(event_loop->thread, NULL); } cf_free(as_event_loops); as_event_loops = NULL; as_event_loop_size = 0; } }
static void as_ev_wakeup(struct ev_loop* loop, ev_async* wakeup, int revents) { // Read command pointers from queue. as_event_loop* event_loop = wakeup->data; void* cmd; pthread_mutex_lock(&event_loop->lock); while (as_queue_pop(&event_loop->queue, &cmd)) { if (cmd) { // Process new command. as_event_command_execute_in_loop(cmd); } else { // Received stop signal. as_event_close_loop(event_loop); return; } } pthread_mutex_unlock(&event_loop->lock); }