diff --git a/include/lighttpd/virtualrequest.h b/include/lighttpd/virtualrequest.h index abc1f7f..1317b99 100644 --- a/include/lighttpd/virtualrequest.h +++ b/include/lighttpd/virtualrequest.h @@ -53,6 +53,7 @@ struct liFilters { struct liVRequestRef { gint refcount; + liWorker *wrk; liVRequest *vr; /* This is only accesible by the worker thread the vrequest belongs to, and it may be NULL if the vrequest is already reset */ }; @@ -116,8 +117,9 @@ LI_API void li_vrequest_free(liVRequest *vr); */ LI_API void li_vrequest_reset(liVRequest *vr, gboolean keepalive); -LI_API liVRequestRef* li_vrequest_acquire_ref(liVRequest *vr); -LI_API liVRequest* li_vrequest_release_ref(liVRequestRef *vr_ref); +LI_API liVRequestRef* li_vrequest_get_ref(liVRequest *vr); +LI_API void li_vrequest_ref_acquire(liVRequestRef *vr_ref); +LI_API liVRequest* li_vrequest_ref_release(liVRequestRef *vr_ref); LI_API liFilter* li_vrequest_add_filter_in(liVRequest *vr, liFilterHandlerCB handle_data, liFilterFreeCB handle_free, gpointer param); LI_API liFilter* li_vrequest_add_filter_out(liVRequest *vr, liFilterHandlerCB handle_data, liFilterFreeCB handle_free, gpointer param); @@ -149,7 +151,7 @@ LI_API gboolean li_vrequest_is_handled(liVRequest *vr); LI_API void li_vrequest_state_machine(liVRequest *vr); LI_API void li_vrequest_joblist_append(liVRequest *vr); -LI_API void li_vrequest_joblist_append_async(liVRequest *vr); +LI_API void li_vrequest_joblist_append_async(liVRequestRef *vr_ref); LI_API gboolean li_vrequest_redirect(liVRequest *vr, GString *uri); diff --git a/src/main/virtualrequest.c b/src/main/virtualrequest.c index a8295be..413ba52 100644 --- a/src/main/virtualrequest.c +++ b/src/main/virtualrequest.c @@ -145,6 +145,7 @@ liVRequest* li_vrequest_new(liConnection *con, liVRequestHandlerCB handle_respon vr->ref = g_slice_new0(liVRequestRef); vr->ref->refcount = 1; vr->ref->vr = vr; + vr->ref->wrk = con->wrk; vr->state = LI_VRS_CLEAN; vr->handle_response_headers = handle_response_headers; @@ -312,17 +313,23 @@ void li_vrequest_reset(liVRequest *vr, gboolean keepalive) { vr->ref = g_slice_new0(liVRequestRef); vr->ref->refcount = 1; vr->ref->vr = vr; + vr->ref->wrk = vr->wrk; } } -liVRequestRef* li_vrequest_acquire_ref(liVRequest *vr) { +liVRequestRef* li_vrequest_get_ref(liVRequest *vr) { liVRequestRef* vr_ref = vr->ref; g_assert(vr_ref->refcount > 0); g_atomic_int_inc(&vr_ref->refcount); return vr_ref; } -liVRequest* li_vrequest_release_ref(liVRequestRef *vr_ref) { +void li_vrequest_ref_acquire(liVRequestRef *vr_ref) { + g_assert(vr_ref->refcount > 0); + g_atomic_int_inc(&vr_ref->refcount); +} + +liVRequest* li_vrequest_ref_release(liVRequestRef *vr_ref) { liVRequest *vr = vr_ref->vr; g_assert(vr_ref->refcount > 0); if (g_atomic_int_dec_and_test(&vr_ref->refcount)) { @@ -648,11 +655,11 @@ void li_vrequest_joblist_append(liVRequest *vr) { ev_timer_start(wrk->loop, &wrk->job_queue_watcher); } -void li_vrequest_joblist_append_async(liVRequest *vr) { - liWorker *wrk = vr->wrk; +void li_vrequest_joblist_append_async(liVRequestRef *vr_ref) { + liWorker *wrk = vr_ref->wrk; GAsyncQueue *const q = wrk->job_async_queue; - if (!g_atomic_int_compare_and_exchange(&vr->queued, 0, 1)) return; /* already in queue */ - g_async_queue_push(q, li_vrequest_acquire_ref(vr)); + li_vrequest_ref_acquire(vr_ref); + g_async_queue_push(q, vr_ref); ev_async_send(wrk->loop, &wrk->job_async_queue_watcher); } diff --git a/src/main/worker.c b/src/main/worker.c index 947df2a..0fed72a 100644 --- a/src/main/worker.c +++ b/src/main/worker.c @@ -196,8 +196,7 @@ static void worker_job_async_queue_cb(struct ev_loop *loop, ev_async *w, int rev UNUSED(revents); while (NULL != (vr_ref = g_async_queue_try_pop(q))) { - if (NULL != (vr = li_vrequest_release_ref(vr_ref))) { - g_assert(g_atomic_int_compare_and_exchange(&vr->queued, 1, 0)); + if (NULL != (vr = li_vrequest_ref_release(vr_ref))) { li_vrequest_state_machine(vr); } } @@ -515,7 +514,7 @@ void li_worker_free(liWorker *wrk) { liVRequest *vr; while (NULL != (vr_ref = g_async_queue_try_pop(q))) { - if (NULL != (vr = li_vrequest_release_ref(vr_ref))) { + if (NULL != (vr = li_vrequest_ref_release(vr_ref))) { g_assert(g_atomic_int_compare_and_exchange(&vr->queued, 1, 0)); li_vrequest_state_machine(vr); }