feat: add blocking step support to http loop
							parent
							
								
									9c01548256
								
							
						
					
					
						commit
						a96ae39523
					
				|  | @ -34,5 +34,5 @@ int main() { | |||
|   lnm_log_init_global(); | ||||
|   lnm_log_register_stdout(lnm_log_level_debug); | ||||
| 
 | ||||
|   printf("res = %i\n", lnm_http_loop_run(hl, 8080, 1, 1)); | ||||
|   printf("res = %i\n", lnm_http_loop_run(hl, 8080, 1, 32)); | ||||
| } | ||||
|  |  | |||
|  | @ -47,6 +47,7 @@ typedef struct lnm_loop_queue { | |||
|   } buf; | ||||
|   size_t head; | ||||
|   size_t tail; | ||||
|   bool empty; | ||||
|   pthread_mutex_t mutex; | ||||
|   pthread_cond_t cond; | ||||
| } lnm_loop_queue; | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| typedef struct lnm_http_step { | ||||
|   lnm_http_step_fn fn; | ||||
|   struct lnm_http_step *next; | ||||
|   bool blocking; | ||||
| } lnm_http_step; | ||||
| 
 | ||||
| typedef enum lnm_http_route_type { | ||||
|  |  | |||
|  | @ -133,11 +133,19 @@ void lnm_http_loop_process_steps(lnm_http_conn *conn) { | |||
|   while ((ctx->cur_step != NULL) && (step != ctx->cur_step)) { | ||||
|     step = ctx->cur_step; | ||||
| 
 | ||||
|     if (step->blocking && (conn->state != lnm_loop_state_req_blocking)) { | ||||
|       conn->state = lnm_loop_state_req_blocking; | ||||
| 
 | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
|     switch (step->fn(conn)) { | ||||
|     case lnm_http_step_err_done: | ||||
|       ctx->cur_step = ctx->cur_step->next; | ||||
|       break; | ||||
|     case lnm_http_step_err_io_needed: | ||||
|       // Ensure steps that require more I/O are executed on the event loop
 | ||||
|       conn->state = lnm_loop_state_req; | ||||
|       break; | ||||
|     case lnm_http_step_err_close: | ||||
|       conn->state = lnm_loop_state_end; | ||||
|  | @ -149,6 +157,7 @@ void lnm_http_loop_process_steps(lnm_http_conn *conn) { | |||
|   } | ||||
| 
 | ||||
|   if (ctx->cur_step == NULL) { | ||||
|     conn->state = lnm_loop_state_res; | ||||
|     ctx->state = lnm_http_loop_state_add_headers; | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -1,9 +1,10 @@ | |||
| #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 = malloc(cap * sizeof(lnm_loop_conn *)); | ||||
|   lnm_loop_conn **arr = calloc(cap, sizeof(lnm_loop_conn *)); | ||||
| 
 | ||||
|   if (arr == NULL) { | ||||
|     return lnm_err_failed_alloc; | ||||
|  | @ -20,6 +21,10 @@ lnm_err lnm_loop_queue_init(lnm_loop_queue **out, size_t cap) { | |||
|   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); | ||||
| 
 | ||||
|  | @ -31,14 +36,15 @@ lnm_err lnm_loop_queue_init(lnm_loop_queue **out, size_t cap) { | |||
| void lnm_loop_queue_push(lnm_loop_queue *q, lnm_loop_conn *conn) { | ||||
|   pthread_mutex_lock(&q->mutex); | ||||
| 
 | ||||
|   while (q->tail == q->head) { | ||||
|   while (q->head == q->tail && !q->empty) { | ||||
|     pthread_cond_wait(&q->cond, &q->mutex); | ||||
|   } | ||||
| 
 | ||||
|   q->buf.arr[q->tail] = conn; | ||||
|   q->buf.arr[q->head] = conn; | ||||
| 
 | ||||
|   // Make sure the index wraps around
 | ||||
|   q->tail = (q->tail + 1) % q->buf.len; | ||||
|   q->head = (q->head + 1) % q->buf.len; | ||||
|   q->empty = false; | ||||
| 
 | ||||
|   // Unlock mutex and signal to waiting threads
 | ||||
|   pthread_mutex_unlock(&q->mutex); | ||||
|  | @ -48,12 +54,14 @@ void lnm_loop_queue_push(lnm_loop_queue *q, lnm_loop_conn *conn) { | |||
| lnm_loop_conn *lnm_loop_queue_pop(lnm_loop_queue *q) { | ||||
|   pthread_mutex_lock(&q->mutex); | ||||
| 
 | ||||
|   while (q->tail == q->head) { | ||||
|   while (q->empty) { | ||||
|     pthread_cond_wait(&q->cond, &q->mutex); | ||||
|   } | ||||
| 
 | ||||
|   lnm_loop_conn *out = q->buf.arr[q->head]; | ||||
|   q->head = (q->head + 1) % q->buf.len; | ||||
|   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); | ||||
|  | @ -66,8 +74,17 @@ 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); | ||||
| 
 | ||||
|     switch (conn->state) { | ||||
|     case lnm_loop_state_req_blocking: | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue