int32_t connector_start(connector_t* con) { if (!con || con->h.fd < 0) return -1; sock_set_nonblock(con->h.fd); sock_set_nodelay(con->h.fd); return reactor_register(con->r, &con->h, EVENT_IN); }
eager_reader_t *eager_reader_new( int fd_to_read, const allocator_t *allocator, size_t buffer_size, size_t max_buffer_count, const char *thread_name) { assert(fd_to_read != INVALID_FD); assert(allocator != NULL); assert(buffer_size > 0); assert(max_buffer_count > 0); assert(thread_name != NULL && *thread_name != '\0'); eager_reader_t *ret = osi_calloc(sizeof(eager_reader_t)); if (!ret) { LOG_ERROR(LOG_TAG, "%s unable to allocate memory for new eager_reader.", __func__); goto error; } ret->allocator = allocator; ret->inbound_fd = fd_to_read; ret->bytes_available_fd = eventfd(0, 0); if (ret->bytes_available_fd == INVALID_FD) { LOG_ERROR(LOG_TAG, "%s unable to create output reading semaphore.", __func__); goto error; } ret->buffer_size = buffer_size; ret->buffers = fixed_queue_new(max_buffer_count); if (!ret->buffers) { LOG_ERROR(LOG_TAG, "%s unable to create buffers queue.", __func__); goto error; } ret->inbound_read_thread = thread_new(thread_name); if (!ret->inbound_read_thread) { LOG_ERROR(LOG_TAG, "%s unable to make reading thread.", __func__); goto error; } ret->inbound_read_object = reactor_register( thread_get_reactor(ret->inbound_read_thread), fd_to_read, ret, inbound_data_waiting, NULL ); return ret; error:; eager_reader_free(ret); return NULL; }
void eager_reader_register(eager_reader_t *reader, reactor_t *reactor, eager_reader_cb read_cb, void *context) { assert(reader != NULL); assert(reactor != NULL); assert(read_cb != NULL); // Make sure the reader isn't currently registered. eager_reader_unregister(reader); reader->outbound_read_ready = read_cb; reader->outbound_context = context; reader->outbound_registration = reactor_register(reactor, reader->bytes_available_fd, reader, internal_outbound_read_ready, NULL); }
void socket_register(socket_t *socket, reactor_t *reactor, void *context, socket_cb read_cb, socket_cb write_cb) { assert(socket != NULL); // Make sure the socket isn't currently registered. socket_unregister(socket); socket->read_ready = read_cb; socket->write_ready = write_cb; socket->context = context; void (*read_fn)(void *) = (read_cb != NULL) ? internal_read_ready : NULL; void (*write_fn)(void *) = (write_cb != NULL) ? internal_write_ready : NULL; socket->reactor_object = reactor_register(reactor, socket->fd, socket, read_fn, write_fn); }
static void *run_thread(void *start_arg) { assert(start_arg != NULL); struct start_arg *start = start_arg; thread_t *thread = start->thread; assert(thread != NULL); if (prctl(PR_SET_NAME, (unsigned long)thread->name) == -1) { ALOGE("%s unable to set thread name: %s", __func__, strerror(errno)); start->error = errno; semaphore_post(start->start_sem); return NULL; } thread->tid = gettid(); semaphore_post(start->start_sem); reactor_object_t work_queue_object; work_queue_object.context = thread->work_queue; work_queue_object.fd = fixed_queue_get_dequeue_fd(thread->work_queue); work_queue_object.interest = REACTOR_INTEREST_READ; work_queue_object.read_ready = work_queue_read_cb; reactor_register(thread->reactor, &work_queue_object); reactor_start(thread->reactor); // Make sure we dispatch all queued work items before exiting the thread. // This allows a caller to safely tear down by enqueuing a teardown // work item and then joining the thread. size_t count = 0; work_item_t *item = fixed_queue_try_dequeue(thread->work_queue); while (item && count <= WORK_QUEUE_CAPACITY) { item->func(item->context); free(item); item = fixed_queue_try_dequeue(thread->work_queue); ++count; } if (count > WORK_QUEUE_CAPACITY) ALOGD("%s growing event queue on shutdown.", __func__); return NULL; }
static void *run_thread(void *start_arg) { assert(start_arg != NULL); struct start_arg *start = start_arg; thread_t *thread = start->thread; assert(thread != NULL); if (prctl(PR_SET_NAME, (unsigned long)thread->name) == -1) { LOG_ERROR("%s unable to set thread name: %s", __func__, strerror(errno)); start->error = errno; semaphore_post(start->start_sem); return NULL; } thread->tid = gettid(); semaphore_post(start->start_sem); int fd = fixed_queue_get_dequeue_fd(thread->work_queue); void *context = thread->work_queue; reactor_object_t *work_queue_object = reactor_register(thread->reactor, fd, context, work_queue_read_cb, NULL); reactor_start(thread->reactor); reactor_unregister(work_queue_object); // Make sure we dispatch all queued work items before exiting the thread. // This allows a caller to safely tear down by enqueuing a teardown // work item and then joining the thread. size_t count = 0; work_item_t *item = fixed_queue_try_dequeue(thread->work_queue); while (item && count <= fixed_queue_capacity(thread->work_queue)) { item->func(item->context); osi_free(item); item = fixed_queue_try_dequeue(thread->work_queue); ++count; } if (count > fixed_queue_capacity(thread->work_queue)) LOG_DEBUG("%s growing event queue on shutdown.", __func__); return NULL; }