diff options
author | Benjamin Otte <otte@gnome.org> | 2009-07-08 17:37:00 +0200 |
---|---|---|
committer | Benjamin Otte <otte@gnome.org> | 2009-07-08 17:37:00 +0200 |
commit | 81ee91ce9622f8bf269fdb2b4e6b18cb617cfcbf (patch) | |
tree | 6120e456039778e9e1440c8e15f7f3c4f2c0afb1 | |
parent | 9e969883459bbc31c8709ea76dc741d6c1e6d64b (diff) |
Lots of fixes for races
-rw-r--r-- | ephy-history.c | 47 |
1 files changed, 40 insertions, 7 deletions
diff --git a/ephy-history.c b/ephy-history.c index 9d8d5b6..f0aad06 100644 --- a/ephy-history.c +++ b/ephy-history.c @@ -395,6 +395,7 @@ typedef struct { guint progress_ms; char *sql; GSList *results; + GCancellable *cancellable; /* need to store these because GSimpleAsyncResult doesn't allow querying */ GAsyncReadyCallback callback; gpointer user_data; @@ -407,13 +408,31 @@ select_data_free (gpointer data) if (select->sql) sqlite3_free (select->sql); + if (select->cancellable) + g_object_unref (select->cancellable); g_slist_foreach (select->results, (GFunc) g_value_array_free, NULL); g_slist_free (select->results); g_slice_free (SelectData, select); } -/* FIXME: abort in idle callback when cancelled */ +static gboolean +ephy_history_complete_in_idle_cb (gpointer _data) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (_data); + SelectData *data = g_simple_async_result_get_op_res_gpointer (simple); + + /* + * Don't complete the async result here, because then we'd + * get multiple cancellation errors - once for every progress + * update plus the final one. + */ + if (!g_cancellable_is_cancelled (data->cancellable)) + g_simple_async_result_complete (simple); + + return FALSE; +} + static void ephy_history_select_emit_partial (EphyHistory *history, GSList *list, @@ -423,14 +442,25 @@ ephy_history_select_emit_partial (EphyHistory *history, { GSimpleAsyncResult *res; SelectData *select; + GSource *source; + + g_assert (list); select = g_slice_new0 (SelectData); select->results = list; + if (cancellable) + select->cancellable = g_object_ref (cancellable); res = g_simple_async_result_new (G_OBJECT (history), callback, user_data, ephy_history_select_async); g_simple_async_result_set_op_res_gpointer (res, select, select_data_free); - g_simple_async_result_complete_in_idle (res); + + source = g_idle_source_new (); + g_source_set_priority (source, G_PRIORITY_DEFAULT); + g_source_set_callback (source, ephy_history_complete_in_idle_cb, res, g_object_unref); + + g_source_attach (source, NULL); + g_source_unref (source); } - + static void ephy_history_select_thread (GSimpleAsyncResult *res, GObject * object, @@ -497,8 +527,8 @@ ephy_history_select_thread (GSimpleAsyncResult *res, counter--; if (counter == 0 || g_timer_elapsed (timer, NULL) > timeout) { - ephy_history_select_emit_partial (history, - select->results, + ephy_history_select_emit_partial (history, + g_slist_reverse (select->results), select->callback, select->user_data, cancellable); @@ -508,10 +538,11 @@ ephy_history_select_thread (GSimpleAsyncResult *res, } g_timer_destroy (timer); - if (check_sqlite_result (history, res, sqlite3_finalize (stmt))) + if (check_sqlite_result (history, res, sqlite3_finalize (stmt)) && + select->results != NULL) { ephy_history_select_emit_partial (history, - select->results, + g_slist_reverse (select->results), select->callback, select->user_data, cancellable); @@ -545,6 +576,8 @@ ephy_history_select_async (EphyHistory * history, select->user_data = user_data; select->initial_results = initial_results; select->progress_ms = progress_ms; + if (cancellable) + select->cancellable = g_object_ref (cancellable); va_start (args, sql); select->sql = sqlite3_vmprintf (sql, args); va_end (args); |