X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=bluesky%2Fstore.c;h=888bd1b07b490b6ae305377c2a8c8c1809c8ac9e;hb=8e686a50b321c7d2d154bd6121dd4a1e982f595d;hp=200cd3e00d487989228213f52b81b1468ac4e36e;hpb=6710eff91ed1a5ee193701ef4b9b28460bb8e95c;p=bluesky.git diff --git a/bluesky/store.c b/bluesky/store.c index 200cd3e..888bd1b 100644 --- a/bluesky/store.c +++ b/bluesky/store.c @@ -97,6 +97,7 @@ BlueSkyStoreAsync *bluesky_store_async_new(BlueSkyStore *store) async->result = -1; async->notifiers = NULL; async->notifier_count = 0; + async->barrier = NULL; async->store_private = NULL; return async; @@ -171,6 +172,22 @@ void bluesky_store_async_add_notifier(BlueSkyStoreAsync *async, 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 * the store implementations. The lock should be held when calling this * function. Any notifier functions will be called, but in a separate thread @@ -190,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; @@ -234,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) @@ -267,7 +282,11 @@ static void notifier_task(gpointer n, gpointer s) 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);