summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2013-02-19 13:35:11 +0100
committerYorhel <git@yorhel.nl>2013-02-19 13:38:37 +0100
commit319b7f93a4e9b4457f4593c9be1ec21500f47f0e (patch)
tree6ea0247da87499e30229bd9395e862f823ea26d8
parent3f1e48f2e00480fdb59a2cc095ba60fd107cdf6c (diff)
evtp: Don't hold a reference on the ev loop when nothing is queued
-rw-r--r--evtp.c8
-rw-r--r--evtp.h9
-rw-r--r--test/evtp.c5
3 files changed, 14 insertions, 8 deletions
diff --git a/evtp.c b/evtp.c
index 11bd7c7..680e957 100644
--- a/evtp.c
+++ b/evtp.c
@@ -75,6 +75,7 @@ static void evtp_async(EV_P_ ev_async *async, int revents) {
items = items->next;
/* Don't use 'first' after this function, application may have free()d it. */
func(first);
+ ev_unref(EV_A);
}
}
@@ -91,6 +92,7 @@ evtp_t *evtp_create(EV_P_ int maxthreads) {
ev_async_init(&tp->async, evtp_async);
ev_async_start(EV_A_ &tp->async);
+ ev_unref(EV_A);
tp->async.data = tp;
#if EV_MULTIPLICITY
tp->loop = loop;
@@ -140,6 +142,7 @@ int evtp_destroy(evtp_t *threadpool) {
pthread_cond_destroy(&threadpool->cond);
pthread_cond_destroy(&threadpool->die_cond);
pthread_mutex_destroy(&threadpool->lock);
+ ev_ref(EV_A);
ev_async_stop(EV_A_ &threadpool->async);
free(threadpool);
return 1;
@@ -247,6 +250,9 @@ static int evtp_new_thread(evtp_t *threadpool) {
int evtp_submit(evtp_work_t *work, evtp_t *threadpool, evtp_func_t work_func, evtp_func_t done_func) {
int rc = 0;
int dosignal = 1;
+#if EV_MULTIPLICITY
+ struct ev_loop *loop = threadpool->loop;
+#endif
work->work_func = work_func;
work->done_func = done_func;
@@ -266,6 +272,8 @@ int evtp_submit(evtp_work_t *work, evtp_t *threadpool, evtp_func_t work_func, ev
pthread_cond_signal(&threadpool->cond);
pthread_mutex_unlock(&threadpool->lock);
+ ev_ref(EV_A);
+
return rc;
}
diff --git a/evtp.h b/evtp.h
index d2d6461..4e744aa 100644
--- a/evtp.h
+++ b/evtp.h
@@ -31,9 +31,7 @@ THE SOFTWARE.
* 3. https://github.com/jech/threadpool
*
* TODO:
- * - Figure out shutdown
* - Convenient create_work_object_and_submit()
- * - Don't hold a ref on the libev loop when nothing is queued?
* - Cancellation?
* - Allow done_func = NULL? (Implies auto-free()-work-object-when-done)
*/
@@ -59,7 +57,12 @@ struct evtp_work_t {
};
-/* Create a new thread pool. May return NULL if malloc() fails. */
+/* Create a new thread pool. May return NULL if malloc() fails.
+ *
+ * The thread pool object itself does not hold a reference on the ev loop. Each
+ * evtp_work_t object in the queue, however, does. This way, ev_run() may quit
+ * even when a thread pool object is alive, but it will never quit as long
+ * there is still work to do. */
evtp_t *evtp_create(EV_P_ int maxthreads);
diff --git a/test/evtp.c b/test/evtp.c
index 4c5f0d6..67d3d37 100644
--- a/test/evtp.c
+++ b/test/evtp.c
@@ -71,14 +71,9 @@ static void done_cb(evtp_work_t *w) {
w = calloc(1, sizeof(evtp_work_t));
w->data = data;
evtp_submit(w, tp, work_cb, done_cb);
- return;
}
}
#endif
-
- /* TODO: Shouldn't be necessary when evtp drops its ref when nothing is queued */
- if(done == 50)
- ev_break(EV_DEFAULT_ EVBREAK_ONE);
}