+ while (async->status != ASYNC_COMPLETE) {
+ g_cond_wait(async->completion_cond, async->lock);
+ }
+
+ g_mutex_unlock(async->lock);
+}
+
+/* Add a notifier function to be called when the operation completes. */
+void bluesky_store_async_add_notifier(BlueSkyStoreAsync *async,
+ GFunc func, gpointer user_data)
+{
+ struct BlueSkyNotifierList *nl = g_new(struct BlueSkyNotifierList, 1);
+ nl->next = async->notifiers;
+ nl->func = func;
+ nl->async = async; bluesky_store_async_ref(async);
+ nl->user_data = user_data;
+ if (async->status == ASYNC_COMPLETE) {
+ g_thread_pool_push(notifier_thread_pool, nl, NULL);
+ } else {
+ async->notifiers = nl;
+ }
+}
+
+/* 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
+ * and without the lock held. */
+void bluesky_store_async_mark_complete(BlueSkyStoreAsync *async)
+{
+ g_return_if_fail(async->status != ASYNC_COMPLETE);
+
+ g_mutex_lock(async->store->lock);
+ async->store->pending--;
+ if (async->store->pending == 0)
+ g_cond_broadcast(async->store->cond_idle);
+ g_mutex_unlock(async->store->lock);
+
+ async->status = ASYNC_COMPLETE;
+ g_cond_broadcast(async->completion_cond);
+
+ while (async->notifiers != NULL) {
+ struct BlueSkyNotifierList *nl = async->notifiers;
+ async->notifiers = nl->next;
+ g_thread_pool_push(notifier_thread_pool, nl, NULL);
+ }