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);
}