as_event_loop* as_event_create_loops(uint32_t capacity) { as_event_send_buffer_size = as_pipe_get_send_buffer_size(); as_event_recv_buffer_size = as_pipe_get_recv_buffer_size(); as_event_loops = cf_malloc(sizeof(as_event_loop) * capacity); if (! as_event_loops) { return 0; } as_event_loop_capacity = capacity; as_event_threads_created = true; for (uint32_t i = 0; i < capacity; i++) { as_event_loop* event_loop = &as_event_loops[i]; event_loop->loop = 0; pthread_mutex_init(&event_loop->lock, 0); event_loop->thread = 0; event_loop->index = i; as_queue_init(&event_loop->pipe_cb_queue, sizeof(as_queued_pipe_cb), AS_EVENT_QUEUE_INITIAL_CAPACITY); event_loop->pipe_cb_calling = false; if (! as_event_create_loop(event_loop)) { as_event_close_loops(); return 0; } as_event_loop_size++; } return as_event_loops; }
static inline void as_ev_init_loop(as_event_loop* event_loop) { as_queue_init(&event_loop->queue, sizeof(void*), AS_EVENT_QUEUE_INITIAL_CAPACITY); ev_async_init(&event_loop->wakeup, as_ev_wakeup); event_loop->wakeup.data = event_loop; ev_async_start(event_loop->loop, &event_loop->wakeup); }
void as_event_register_external_loop(as_event_loop* event_loop) { // This method is only called when user sets an external event loop. event_loop->wakeup = cf_malloc(sizeof(uv_async_t)); as_queue_init(&event_loop->queue, sizeof(as_uv_command), AS_EVENT_QUEUE_INITIAL_CAPACITY); // Assume uv_async_init is called on the same thread as the event loop. uv_async_init(event_loop->loop, event_loop->wakeup, as_uv_wakeup); }
bool as_event_create_loop(as_event_loop* event_loop) { event_loop->wakeup = 0; as_queue_init(&event_loop->queue, sizeof(as_uv_command), AS_EVENT_QUEUE_INITIAL_CAPACITY); as_uv_thread_data thread_data; thread_data.event_loop = event_loop; as_monitor_init(&thread_data.monitor); if (pthread_create(&event_loop->thread, NULL, as_uv_worker, &thread_data) != 0) { return false; } // Must wait until uv_async_init() is called in event loop thread. as_monitor_wait(&thread_data.monitor); as_monitor_destroy(&thread_data.monitor); return true; }
as_event_loop* as_event_set_external_loop(void* loop) { uint32_t current = ck_pr_faa_32(&as_event_loop_size, 1); if (current >= as_event_loop_capacity) { as_log_error("Failed to add external loop. Capacity is %u", as_event_loop_capacity); return 0; } as_event_loop* event_loop = &as_event_loops[current]; event_loop->loop = loop; pthread_mutex_init(&event_loop->lock, 0); event_loop->thread = pthread_self(); // Current thread must be same as event loop thread! event_loop->index = current; as_queue_init(&event_loop->pipe_cb_queue, sizeof(as_queued_pipe_cb), AS_EVENT_QUEUE_INITIAL_CAPACITY); event_loop->pipe_cb_calling = false; as_event_register_external_loop(event_loop); return event_loop; }