/* returns true if callback was called directly */ static gboolean collect_send_result(liWorker *ctx, liCollectInfo *ci) { if (!g_atomic_int_dec_and_test(&ci->counter)) return FALSE; /* not all workers done yet */ if (g_atomic_int_get(&ctx->srv->exiting)) { /* cleanup state, just call the callback with complete = FALSE */ ci->cb(ci->cbdata, ci->fdata, ci->results, FALSE); collect_info_free(ci); return TRUE; } else { /* no worker is freed yet */ return collect_insert_callback(ctx, ci); } }
/* returns true if callback was called directly */ static gboolean collect_insert_callback(liWorker *ctx, liCollectInfo *ci) { if (ctx == ci->wrk) { /* we are in the destiation context */ ci->cb(ci->cbdata, ci->fdata, ci->results, !ci->stopped); collect_info_free(ci); return TRUE; } else { liWorker *wrk = ci->wrk; collect_job *j = g_slice_new(collect_job); j->type = COLLECT_CB; j->ci = ci; g_async_queue_push(wrk->collect_queue, j); ev_async_send(wrk->loop, &wrk->collect_watcher); } return FALSE; }
void li_collect_watcher_cb(liEventBase *watcher, int events) { liWorker *wrk = LI_CONTAINER_OF(li_event_async_from(watcher), liWorker, collect_watcher); collect_job *j; UNUSED(events); while (NULL != (j = (collect_job*) g_async_queue_try_pop(wrk->collect_queue))) { liCollectInfo *ci = j->ci; switch (j->type) { case COLLECT_FUNC: g_ptr_array_index(ci->results, wrk->ndx) = ci->func(wrk, ci->fdata); collect_send_result(wrk, ci); break; case COLLECT_CB: ci->cb(ci->cbdata, ci->fdata, ci->results, !ci->stopped); collect_info_free(ci); break; } g_slice_free(collect_job, j); } }
void li_collect_watcher_cb(struct ev_loop *loop, ev_async *w, int revents) { liWorker *wrk = (liWorker*) w->data; collect_job *j; UNUSED(loop); UNUSED(revents); while (NULL != (j = (collect_job*) g_async_queue_try_pop(wrk->collect_queue))) { liCollectInfo *ci = j->ci; switch (j->type) { case COLLECT_FUNC: g_ptr_array_index(ci->results, wrk->ndx) = ci->func(wrk, ci->fdata); collect_send_result(wrk, ci); break; case COLLECT_CB: ci->cb(ci->cbdata, ci->fdata, ci->results, !ci->stopped); collect_info_free(ci); break; } g_slice_free(collect_job, j); } }