fix: transparently support blocking work without worker threads

This commit is contained in:
Jef Roosens 2024-02-14 12:43:58 +01:00
parent 1b8ba305b5
commit 1f63f06e0c
Signed by: Jef Roosens
GPG key ID: B75D4F293C7052DB
8 changed files with 62 additions and 46 deletions

View file

@ -9,6 +9,6 @@ void lnm_loop_conn_free(lnm_loop *l, lnm_loop_conn *conn);
lnm_err lnm_loop_accept(lnm_loop *l);
void lnm_loop_conn_io(lnm_loop *l, lnm_loop_conn *conn);
void lnm_loop_conn_advance(lnm_loop *l, lnm_loop_conn *conn);
#endif

View file

@ -28,7 +28,8 @@ lnm_err lnm_http_loop_init(lnm_http_loop **out, void *c_gctx,
return lnm_err_ok;
}
lnm_err lnm_http_step_init(lnm_http_step **out, lnm_http_step_fn fn) {
lnm_err lnm_http_step_append(lnm_http_step **out, lnm_http_step_fn fn,
bool blocking) {
lnm_http_step *step = calloc(1, sizeof(lnm_http_step));
if (step == NULL) {
@ -36,19 +37,14 @@ lnm_err lnm_http_step_init(lnm_http_step **out, lnm_http_step_fn fn) {
}
step->fn = fn;
*out = step;
step->blocking = blocking;
return lnm_err_ok;
}
lnm_err lnm_http_step_append(lnm_http_step **out, lnm_http_step *step,
lnm_http_step_fn fn) {
LNM_RES(lnm_http_step_init(out, fn));
if (step != NULL) {
step->next = *out;
if ((*out) != NULL) {
(*out)->next = step;
}
*out = step;
return lnm_err_ok;
}

View file

@ -196,7 +196,7 @@ lnm_err lnm_loop_run(lnm_loop *l) {
lnm_loop_conn *conn = events[i].data.ptr;
// At this point, state is always an IO state
lnm_loop_conn_io(l, conn);
lnm_loop_conn_advance(l, conn);
lnm_loop_conn_schedule(l, conn);
}
}

View file

@ -67,14 +67,30 @@ void lnm_loop_conn_io_res(lnm_loop *l, lnm_loop_conn *conn) {
} while (conn->state == lnm_loop_state_res_io);
}
void lnm_loop_conn_io(lnm_loop *l, lnm_loop_conn *conn) {
switch (conn->state) {
case lnm_loop_state_req_io:
lnm_loop_conn_io_req(l, conn);
break;
case lnm_loop_state_res_io:
lnm_loop_conn_io_res(l, conn);
break;
default:;
void lnm_loop_conn_advance(lnm_loop *l, lnm_loop_conn *conn) {
do {
switch (conn->state) {
case lnm_loop_state_req_io:
lnm_loop_conn_io_req(l, conn);
break;
case lnm_loop_state_res_io:
lnm_loop_conn_io_res(l, conn);
break;
case lnm_loop_state_req_work:
do {
l->data_read(conn);
} while (conn->state == lnm_loop_state_req_work);
break;
case lnm_loop_state_res_work:
do {
l->data_write(conn);
} while (conn->state == lnm_loop_state_res_work);
break;
default:;
}
}
// Execute all blocking work if we're running in single-threaded mode
while (l->wq == NULL && (conn->state == lnm_loop_state_req_work ||
conn->state == lnm_loop_state_res_work));
}

View file

@ -86,16 +86,7 @@ void lnm_loop_worker_run(void *arg) {
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_work:
l->data_read(conn);
break;
case lnm_loop_state_res_work:
l->data_write(conn);
// Other states shouldn't even end up here, so we ignore them
default:;
}
lnm_loop_conn_advance(l, conn);
lnm_loop_conn_schedule(l, conn);
}
}