void thread_free(thread_t *thread) { if (!thread) return; thread_stop(thread); pthread_join(thread->pthread, NULL); fixed_queue_free(thread->work_queue, free); reactor_free(thread->reactor); free(thread); }
void thread_free(thread_t *thread) { if (!thread) return; thread_stop(thread); thread_join(thread); fixed_queue_free(thread->work_queue, osi_free); reactor_free(thread->reactor); osi_free(thread); }
reactor_t *reactor_new(void) { reactor_t *ret = (reactor_t *)osi_calloc(sizeof(reactor_t)); if (!ret) return NULL; ret->epoll_fd = INVALID_FD; ret->event_fd = INVALID_FD; ret->epoll_fd = epoll_create(MAX_EVENTS); if (ret->epoll_fd == INVALID_FD) { LOG_ERROR("%s unable to create epoll instance: %s", __func__, strerror(errno)); goto error; } ret->event_fd = eventfd(0, 0); if (ret->event_fd == INVALID_FD) { LOG_ERROR("%s unable to create eventfd: %s", __func__, strerror(errno)); goto error; } pthread_mutex_init(&ret->list_lock, NULL); ret->invalidation_list = list_new(NULL); if (!ret->invalidation_list) { LOG_ERROR("%s unable to allocate object invalidation list.", __func__); goto error; } struct epoll_event event; memset(&event, 0, sizeof(event)); event.events = EPOLLIN; event.data.ptr = NULL; if (epoll_ctl(ret->epoll_fd, EPOLL_CTL_ADD, ret->event_fd, &event) == -1) { LOG_ERROR("%s unable to register eventfd with epoll set: %s", __func__, strerror(errno)); goto error; } return ret; error:; reactor_free(ret); return NULL; }
thread_t *thread_new_sized(const char *name, size_t work_queue_capacity) { assert(name != NULL); assert(work_queue_capacity != 0); thread_t *ret = osi_calloc(sizeof(thread_t)); if (!ret) goto error; ret->reactor = reactor_new(); if (!ret->reactor) goto error; ret->work_queue = fixed_queue_new(work_queue_capacity); if (!ret->work_queue) goto error; // Start is on the stack, but we use a semaphore, so it's safe struct start_arg start; start.start_sem = semaphore_new(0); if (!start.start_sem) goto error; strncpy(ret->name, name, THREAD_NAME_MAX); start.thread = ret; start.error = 0; pthread_create(&ret->pthread, NULL, run_thread, &start); semaphore_wait(start.start_sem); semaphore_free(start.start_sem); if (start.error) goto error; return ret; error:; if (ret) { fixed_queue_free(ret->work_queue, osi_free); reactor_free(ret->reactor); } osi_free(ret); return NULL; }
thread_t *thread_new(const char *name) { assert(name != NULL); // Start is on the stack, but we use a semaphore, so it's safe thread_t *ret = calloc(1, sizeof(thread_t)); if (!ret) goto error; ret->reactor = reactor_new(); if (!ret->reactor) goto error; ret->work_queue = fixed_queue_new(WORK_QUEUE_CAPACITY); if (!ret->work_queue) goto error; struct start_arg start; start.start_sem = semaphore_new(0); if (!start.start_sem) goto error; strncpy(ret->name, name, THREAD_NAME_MAX); start.thread = ret; start.error = 0; pthread_create(&ret->pthread, NULL, run_thread, &start); semaphore_wait(start.start_sem); semaphore_free(start.start_sem); if (start.error) goto error; return ret; error:; if (ret) { fixed_queue_free(ret->work_queue, free); reactor_free(ret->reactor); } free(ret); return NULL; }