Only treat an async storage operation as finished when notifiers finish.
authorMichael Vrable <mvrable@cs.ucsd.edu>
Fri, 5 Mar 2010 00:16:52 +0000 (16:16 -0800)
committerMichael Vrable <mvrable@cs.ucsd.edu>
Fri, 5 Mar 2010 00:16:52 +0000 (16:16 -0800)
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
bluesky/store.c

index 4609226..058c5bd 100644 (file)
@@ -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. */
 
index d83fe03..200cd3e 100644 (file)
@@ -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(&notifier->async->notifier_count)) {
+        g_cond_broadcast(notifier->async->completion_cond);
+    }
     bluesky_store_async_unref(notifier->async);
     g_free(notifier);
 }