From 6710eff91ed1a5ee193701ef4b9b28460bb8e95c Mon Sep 17 00:00:00 2001 From: Michael Vrable Date: Thu, 4 Mar 2010 16:16:52 -0800 Subject: [PATCH] Only treat an async storage operation as finished when notifiers finish. There's still a bit more work to be done with barriers, but this eliminates some race conditions in some usages. --- bluesky/bluesky-private.h | 1 + bluesky/store.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/bluesky/bluesky-private.h b/bluesky/bluesky-private.h index 4609226..058c5bd 100644 --- a/bluesky/bluesky-private.h +++ b/bluesky/bluesky-private.h @@ -63,6 +63,7 @@ typedef struct { int result; /* Result code; 0 for success. */ struct BlueSkyNotifierList *notifiers; + gint notifier_count; bluesky_time_hires start_time; /* Time operation was submitted. */ diff --git a/bluesky/store.c b/bluesky/store.c index d83fe03..200cd3e 100644 --- a/bluesky/store.c +++ b/bluesky/store.c @@ -96,6 +96,7 @@ BlueSkyStoreAsync *bluesky_store_async_new(BlueSkyStore *store) async->data = NULL; async->result = -1; async->notifiers = NULL; + async->notifier_count = 0; async->store_private = NULL; return async; @@ -143,7 +144,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 +157,18 @@ 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); } /* Mark an asynchronous operation as complete. This should only be called by @@ -261,6 +266,9 @@ 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_cond_broadcast(notifier->async->completion_cond); + } bluesky_store_async_unref(notifier->async); g_free(notifier); } -- 2.20.1