93 lines
1.9 KiB
C
93 lines
1.9 KiB
C
#include <sys/epoll.h>
|
|
|
|
#include "lnm/log.h"
|
|
#include "lnm/loop.h"
|
|
|
|
lnm_err lnm_loop_queue_init(lnm_loop_queue **out, size_t cap) {
|
|
lnm_loop_conn **arr = calloc(cap, sizeof(lnm_loop_conn *));
|
|
|
|
if (arr == NULL) {
|
|
return lnm_err_failed_alloc;
|
|
}
|
|
|
|
lnm_loop_queue *q = calloc(1, sizeof(lnm_loop_queue));
|
|
|
|
if (q == NULL) {
|
|
free(arr);
|
|
|
|
return lnm_err_failed_alloc;
|
|
}
|
|
|
|
q->buf.arr = arr;
|
|
q->buf.len = cap;
|
|
|
|
q->tail = 0;
|
|
q->head = 0;
|
|
q->empty = true;
|
|
|
|
pthread_mutex_init(&q->mutex, NULL);
|
|
pthread_cond_init(&q->cond, NULL);
|
|
|
|
*out = q;
|
|
|
|
return lnm_err_ok;
|
|
}
|
|
|
|
void lnm_loop_queue_push(lnm_loop_queue *q, lnm_loop_conn *conn) {
|
|
pthread_mutex_lock(&q->mutex);
|
|
|
|
while (q->head == q->tail && !q->empty) {
|
|
pthread_cond_wait(&q->cond, &q->mutex);
|
|
}
|
|
|
|
q->buf.arr[q->head] = conn;
|
|
|
|
// Make sure the index wraps around
|
|
q->head = (q->head + 1) % q->buf.len;
|
|
q->empty = false;
|
|
|
|
// Unlock mutex and signal to waiting threads
|
|
pthread_mutex_unlock(&q->mutex);
|
|
pthread_cond_signal(&q->cond);
|
|
}
|
|
|
|
lnm_loop_conn *lnm_loop_queue_pop(lnm_loop_queue *q) {
|
|
pthread_mutex_lock(&q->mutex);
|
|
|
|
while (q->empty) {
|
|
pthread_cond_wait(&q->cond, &q->mutex);
|
|
}
|
|
|
|
lnm_loop_conn *out = q->buf.arr[q->tail];
|
|
|
|
q->tail = (q->tail + 1) % q->buf.len;
|
|
q->empty = q->tail == q->head;
|
|
|
|
// Unlock mutex and signal to waiting threads
|
|
pthread_mutex_unlock(&q->mutex);
|
|
pthread_cond_signal(&q->cond);
|
|
|
|
return out;
|
|
}
|
|
|
|
void lnm_loop_worker_run(void *arg) {
|
|
lnm_loop *l = arg;
|
|
lnm_loop_queue *q = l->wq;
|
|
|
|
// Get thread ID by incrementing counter
|
|
pthread_mutex_lock(&l->threads.mutex);
|
|
|
|
int thread_id = l->threads.worker_count;
|
|
l->threads.worker_count++;
|
|
|
|
pthread_mutex_unlock(&l->threads.mutex);
|
|
|
|
while (1) {
|
|
lnm_loop_conn *conn = lnm_loop_queue_pop(q);
|
|
lnm_ldebug("loop", "worker %i processing fd %i", thread_id, conn->fd);
|
|
|
|
lnm_loop_conn_advance(l, conn);
|
|
lnm_loop_conn_schedule(l, conn);
|
|
}
|
|
}
|