From b6a62382cb0b9029052f81151a578d8ce572c703 Mon Sep 17 00:00:00 2001 From: Claudio Saavedra Date: Fri, 31 Aug 2012 19:28:11 +0300 Subject: ephy-history-service: Do not emit signals from the history service thread We were naively emitting a few signals from the history service thread while doing this is not thread safe. Add a few helper methods to run this in a main loop idle. https://bugzilla.gnome.org/show_bug.cgi?id=683040 --- lib/history/ephy-history-service.c | 88 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) (limited to 'lib/history/ephy-history-service.c') diff --git a/lib/history/ephy-history-service.c b/lib/history/ephy-history-service.c index ffe302b22..3d7a2fdbf 100644 --- a/lib/history/ephy-history-service.c +++ b/lib/history/ephy-history-service.c @@ -479,6 +479,35 @@ ephy_history_service_execute_job_callback (gpointer data) return FALSE; } +typedef struct { + EphyHistoryService *service; + gpointer user_data; + GDestroyNotify destroy_func; +} SignalEmissionContext; + +static void +signal_emission_context_free (SignalEmissionContext *ctx) +{ + g_object_unref (ctx->service); + if (ctx->destroy_func && ctx->user_data) + ctx->destroy_func (ctx->user_data); + g_slice_free (SignalEmissionContext, ctx); +} + +static SignalEmissionContext * +signal_emission_context_new (EphyHistoryService *service, + gpointer user_data, + GDestroyNotify destroy_func) +{ + SignalEmissionContext *ctx = g_slice_new0 (SignalEmissionContext); + + ctx->service = g_object_ref (service); + ctx->user_data = user_data; + ctx->destroy_func = destroy_func; + + return ctx; +} + static gboolean ephy_history_service_execute_add_visit_helper (EphyHistoryService *self, EphyHistoryPageVisit *visit) { @@ -710,6 +739,16 @@ ephy_history_service_query_hosts (EphyHistoryService *self, ephy_history_service_send_message (self, message); } +static gboolean +set_url_title_signal_emit (SignalEmissionContext *ctx) +{ + EphyHistoryURL *url = (EphyHistoryURL *)ctx->user_data; + + g_signal_emit (ctx->service, signals[URL_TITLE_CHANGED], 0, url->url, url->title); + + return FALSE; +} + static gboolean ephy_history_service_execute_set_url_title (EphyHistoryService *self, EphyHistoryURL *url, @@ -722,11 +761,19 @@ ephy_history_service_execute_set_url_title (EphyHistoryService *self, g_free (title); return FALSE; } else { + SignalEmissionContext *ctx; + g_free (url->title); url->title = title; ephy_history_service_update_url_row (self, url); ephy_history_service_schedule_commit (self); - g_signal_emit (self, signals[URL_TITLE_CHANGED], 0, url->url, url->title); + + ctx = signal_emission_context_new (self, + ephy_history_url_copy (url), + (GDestroyNotify)ephy_history_url_free); + g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc)set_url_title_signal_emit, + ctx, (GDestroyNotify)signal_emission_context_free); return TRUE; } } @@ -946,6 +993,16 @@ ephy_history_service_get_host_for_url (EphyHistoryService *self, ephy_history_service_send_message (self, message); } +static gboolean +delete_urls_signal_emit (SignalEmissionContext *ctx) +{ + char *url = (char *)ctx->user_data; + + g_signal_emit (ctx->service, signals[URL_DELETED], 0, url); + + return FALSE; +} + static gboolean ephy_history_service_execute_delete_urls (EphyHistoryService *self, GList *urls, @@ -953,11 +1010,18 @@ ephy_history_service_execute_delete_urls (EphyHistoryService *self, { GList *l; EphyHistoryURL *url; + SignalEmissionContext *ctx; for (l = urls; l != NULL; l = l->next) { url = l->data; ephy_history_service_delete_url (self, url); - g_signal_emit (self, signals[URL_DELETED], 0, url->url); + + ctx = signal_emission_context_new (self, g_strdup (url->url), + (GDestroyNotify) g_free); + g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc)delete_urls_signal_emit, + ctx, + (GDestroyNotify)signal_emission_context_free); } ephy_history_service_delete_orphan_hosts (self); @@ -966,15 +1030,33 @@ ephy_history_service_execute_delete_urls (EphyHistoryService *self, return TRUE; } +static gboolean +delete_host_signal_emit (SignalEmissionContext *ctx) +{ + char *host = (char *)ctx->user_data; + + g_signal_emit (ctx->service, signals[HOST_DELETED], 0, host); + + return FALSE; +} + static gboolean ephy_history_service_execute_delete_host (EphyHistoryService *self, EphyHistoryHost *host, EphyHistoryJobCallback callback, gpointer user_data) { + SignalEmissionContext *ctx; + ephy_history_service_delete_host_row (self, host); ephy_history_service_schedule_commit (self); - g_signal_emit (self, signals[HOST_DELETED], 0, host->url); + + ctx = signal_emission_context_new (self, g_strdup (host->url), + (GDestroyNotify)g_free); + g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc) delete_host_signal_emit, + ctx, + (GDestroyNotify) signal_emission_context_free); return TRUE; } -- cgit v1.2.3