X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=bluesky%2Fstore.c;h=888bd1b07b490b6ae305377c2a8c8c1809c8ac9e;hb=8e686a50b321c7d2d154bd6121dd4a1e982f595d;hp=d83fe037717ea1778c51bc64dc4022b3b7d49567;hpb=ea04d8bdad2da0b59fed45d8ea0128bdba2eb792;p=bluesky.git diff --git a/bluesky/store.c b/bluesky/store.c index d83fe03..888bd1b 100644 --- a/bluesky/store.c +++ b/bluesky/store.c @@ -96,6 +96,8 @@ BlueSkyStoreAsync *bluesky_store_async_new(BlueSkyStore *store) async->data = NULL; async->result = -1; async->notifiers = NULL; + async->notifier_count = 0; + async->barrier = NULL; async->store_private = NULL; return async; @@ -143,7 +145,8 @@ void bluesky_store_async_wait(BlueSkyStoreAsync *async) return; } - while (async->status != ASYNC_COMPLETE) { + while (async->status != ASYNC_COMPLETE + || g_atomic_int_get(&async->notifier_count) > 0) { g_cond_wait(async->completion_cond, async->lock); } @@ -155,15 +158,34 @@ void bluesky_store_async_add_notifier(BlueSkyStoreAsync *async, GFunc func, gpointer user_data) { struct BlueSkyNotifierList *nl = g_new(struct BlueSkyNotifierList, 1); + g_mutex_lock(async->lock); nl->next = async->notifiers; nl->func = func; nl->async = async; bluesky_store_async_ref(async); nl->user_data = user_data; + g_atomic_int_inc(&async->notifier_count); if (async->status == ASYNC_COMPLETE) { g_thread_pool_push(notifier_thread_pool, nl, NULL); } else { async->notifiers = nl; } + g_mutex_unlock(async->lock); +} + +static void op_complete(gpointer a, gpointer b) +{ + BlueSkyStoreAsync *barrier = (BlueSkyStoreAsync *)b; + + bluesky_store_async_ref(barrier); + g_mutex_lock(barrier->lock); + barrier->store_private + = GINT_TO_POINTER(GPOINTER_TO_INT(barrier->store_private) - 1); + if (GPOINTER_TO_INT(barrier->store_private) == 0 + && barrier->status != ASYNC_NEW) { + bluesky_store_async_mark_complete(barrier); + } + g_mutex_unlock(barrier->lock); + bluesky_store_async_unref(barrier); } /* Mark an asynchronous operation as complete. This should only be called by @@ -185,6 +207,9 @@ void bluesky_store_async_mark_complete(BlueSkyStoreAsync *async) async->status = ASYNC_COMPLETE; g_cond_broadcast(async->completion_cond); + if (async->barrier != NULL && async->notifiers == NULL) + op_complete(async, async->barrier); + while (async->notifiers != NULL) { struct BlueSkyNotifierList *nl = async->notifiers; async->notifiers = nl->next; @@ -229,31 +254,26 @@ void bluesky_store_async_submit(BlueSkyStoreAsync *async) bluesky_store_async_wait(async); } -static void op_complete(gpointer a, gpointer b) -{ - BlueSkyStoreAsync *barrier = (BlueSkyStoreAsync *)b; - - bluesky_store_async_ref(barrier); - g_mutex_lock(barrier->lock); - barrier->store_private - = GINT_TO_POINTER(GPOINTER_TO_INT(barrier->store_private) - 1); - if (GPOINTER_TO_INT(barrier->store_private) == 0 - && barrier->status != ASYNC_NEW) { - bluesky_store_async_mark_complete(barrier); - } - g_mutex_unlock(barrier->lock); - bluesky_store_async_unref(barrier); -} - /* Add the given operation to the barrier. The barrier will not complete until * all operations added to it have completed. */ void bluesky_store_add_barrier(BlueSkyStoreAsync *barrier, BlueSkyStoreAsync *async) { g_return_if_fail(barrier->op == STORE_OP_BARRIER); + + g_mutex_lock(barrier->lock); barrier->store_private = GINT_TO_POINTER(GPOINTER_TO_INT(barrier->store_private) + 1); - bluesky_store_async_add_notifier(async, op_complete, barrier); + g_mutex_unlock(barrier->lock); + + g_mutex_lock(async->lock); + if (async->barrier == NULL) { + async->barrier = barrier; + } else { + g_warning("Adding async to more than one barrier!\n"); + bluesky_store_async_add_notifier(async, op_complete, barrier); + } + g_mutex_unlock(async->lock); } static void notifier_task(gpointer n, gpointer s) @@ -261,6 +281,13 @@ static void notifier_task(gpointer n, gpointer s) struct BlueSkyNotifierList *notifier = (struct BlueSkyNotifierList *)n; notifier->func(notifier->async, notifier->user_data); + if (g_atomic_int_dec_and_test(¬ifier->async->notifier_count)) { + g_mutex_lock(notifier->async->lock); + if (notifier->async->barrier != NULL) + op_complete(notifier->async, notifier->async->barrier); + g_cond_broadcast(notifier->async->completion_cond); + g_mutex_unlock(notifier->async->lock); + } bluesky_store_async_unref(notifier->async); g_free(notifier); }