diff options
author | Milan Crha <mcrha@redhat.com> | 2011-11-24 23:35:59 +0800 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2011-11-24 23:36:42 +0800 |
commit | 4169ce41cc34d992ebd63b1bcc8f604e69aea89a (patch) | |
tree | 1aba982292305af36dc6873f487d67443c34f277 | |
parent | 2eb60688a1955a95c3a040bd98f76bb67e3ff3ed (diff) | |
download | gsoc2013-evolution-4169ce41cc34d992ebd63b1bcc8f604e69aea89a.tar gsoc2013-evolution-4169ce41cc34d992ebd63b1bcc8f604e69aea89a.tar.gz gsoc2013-evolution-4169ce41cc34d992ebd63b1bcc8f604e69aea89a.tar.bz2 gsoc2013-evolution-4169ce41cc34d992ebd63b1bcc8f604e69aea89a.tar.lz gsoc2013-evolution-4169ce41cc34d992ebd63b1bcc8f604e69aea89a.tar.xz gsoc2013-evolution-4169ce41cc34d992ebd63b1bcc8f604e69aea89a.tar.zst gsoc2013-evolution-4169ce41cc34d992ebd63b1bcc8f604e69aea89a.zip |
Bug #664634 - Deadlock when processing completed tasks filter
-rw-r--r-- | calendar/gui/e-cal-model.c | 2 | ||||
-rw-r--r-- | calendar/gui/e-task-table.c | 244 | ||||
-rw-r--r-- | modules/calendar/e-task-shell-view-private.c | 30 | ||||
-rw-r--r-- | modules/calendar/e-task-shell-view-private.h | 1 |
4 files changed, 165 insertions, 112 deletions
diff --git a/calendar/gui/e-cal-model.c b/calendar/gui/e-cal-model.c index 4428d31cbd..fb9898775b 100644 --- a/calendar/gui/e-cal-model.c +++ b/calendar/gui/e-cal-model.c @@ -3752,7 +3752,9 @@ e_cal_model_generate_instances_sync (ECalModel *model, GPtrArray * e_cal_model_get_object_array (ECalModel *model) { + g_return_val_if_fail (model != NULL, NULL); g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL); + g_return_val_if_fail (model->priv != NULL, NULL); return model->priv->objects; } diff --git a/calendar/gui/e-task-table.c b/calendar/gui/e-task-table.c index 0a38889e2d..e052e82357 100644 --- a/calendar/gui/e-task-table.c +++ b/calendar/gui/e-task-table.c @@ -66,6 +66,7 @@ struct _ETaskTablePrivate { gpointer shell_view; /* weak pointer */ ECalModel *model; + GCancellable *completed_cancellable; /* when processing completed tasks */ GtkTargetList *copy_target_list; GtkTargetList *paste_target_list; @@ -383,6 +384,12 @@ task_table_dispose (GObject *object) priv = E_TASK_TABLE (object)->priv; + if (priv->completed_cancellable) { + g_cancellable_cancel (priv->completed_cancellable); + g_object_unref (priv->completed_cancellable); + priv->completed_cancellable = NULL; + } + if (priv->shell_view != NULL) { g_object_remove_weak_pointer ( G_OBJECT (priv->shell_view), &priv->shell_view); @@ -1474,6 +1481,8 @@ task_table_init (ETaskTable *task_table) task_table->priv = G_TYPE_INSTANCE_GET_PRIVATE ( task_table, E_TYPE_TASK_TABLE, ETaskTablePrivate); + task_table->priv->completed_cancellable = NULL; + target_list = gtk_target_list_new (NULL, 0); e_target_list_add_calendar_targets (target_list, 0); task_table->priv->copy_target_list = target_list; @@ -1634,62 +1643,79 @@ e_task_table_get_paste_target_list (ETaskTable *task_table) } static void -hide_completed_rows (ECalModel *model, - GList *clients_list, - gchar *hide_sexp, - GPtrArray *comp_objects) +task_table_get_object_list_async (GList *clients_list, + const gchar *sexp, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer callback_data) { GList *l; - GSList *m, *objects; - ECalClient *client; - gint pos; - gboolean changed = FALSE; for (l = clients_list; l != NULL; l = l->next) { - GError *error = NULL; + ECalClient *client = l->data; - client = l->data; + e_cal_client_get_object_list ( + client, sexp, cancellable, + callback, callback_data); + } +} - e_cal_client_get_object_list_sync ( - client, hide_sexp, &objects, NULL, &error); +static void +hide_completed_rows_ready (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + ECalModel *model = user_data; + GSList *m, *objects; + gboolean changed = FALSE; + gint pos; + GPtrArray *comp_objects; + GError *error = NULL; - if (error != NULL) { - g_warning ( - "%s: Could not get the objects: %s", - G_STRFUNC, error->message); - g_error_free (error); - continue; - } + if (!e_cal_client_get_object_list_finish (E_CAL_CLIENT (source_object), result, &objects, &error)) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && + !g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED)) { + ESource *source = e_client_get_source (E_CLIENT (source_object)); - for (m = objects; m; m = m->next) { - ECalModelComponent *comp_data; - ECalComponentId *id; - ECalComponent *comp = e_cal_component_new (); - - e_cal_component_set_icalcomponent ( - comp, icalcomponent_new_clone (m->data)); - id = e_cal_component_get_id (comp); - - comp_data = e_cal_model_get_component_for_uid (model, id); - if (comp_data != NULL) { - e_table_model_pre_change (E_TABLE_MODEL (model)); - pos = get_position_in_array ( - comp_objects, comp_data); - e_table_model_row_deleted ( - E_TABLE_MODEL (model), pos); - changed = TRUE; - - if (g_ptr_array_remove (comp_objects, comp_data)) - g_object_unref (comp_data); - } - e_cal_component_free_id (id); - g_object_unref (comp); + g_debug ("%s: Could not get the objects from '%s': %s", + G_STRFUNC, + source ? e_source_peek_name (source) : "???", + error ? error->message : "Uknown error"); } + g_clear_error (&error); + return; + } - g_slist_foreach (objects, (GFunc) icalcomponent_free, NULL); - g_slist_free (objects); + comp_objects = e_cal_model_get_object_array (model); + g_return_if_fail (comp_objects != NULL); + + for (m = objects; m; m = m->next) { + ECalModelComponent *comp_data; + ECalComponentId *id; + ECalComponent *comp = e_cal_component_new (); + + e_cal_component_set_icalcomponent ( + comp, icalcomponent_new_clone (m->data)); + id = e_cal_component_get_id (comp); + + comp_data = e_cal_model_get_component_for_uid (model, id); + if (comp_data != NULL) { + e_table_model_pre_change (E_TABLE_MODEL (model)); + pos = get_position_in_array ( + comp_objects, comp_data); + e_table_model_row_deleted ( + E_TABLE_MODEL (model), pos); + changed = TRUE; + + if (g_ptr_array_remove (comp_objects, comp_data)) + g_object_unref (comp_data); + } + e_cal_component_free_id (id); + g_object_unref (comp); } + e_cal_client_free_icalcomp_slist (objects); + if (changed) { /* To notify about changes, because in call of * row_deleted there are still all events. */ @@ -1698,68 +1724,71 @@ hide_completed_rows (ECalModel *model, } static void -show_completed_rows (ECalModel *model, - GList *clients_list, - gchar *show_sexp, - GPtrArray *comp_objects) +show_completed_rows_ready (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - GList *l; - GSList *m, *objects; ECalClient *client; + ECalModel *model = user_data; + GSList *m, *objects; + GPtrArray *comp_objects; + GError *error = NULL; - for (l = clients_list; l != NULL; l = l->next) { - GError *error = NULL; + if (!e_cal_client_get_object_list_finish (E_CAL_CLIENT (source_object), result, &objects, &error)) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && + !g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED)) { + ESource *source = e_client_get_source (E_CLIENT (source_object)); - client = l->data; + g_debug ("%s: Could not get the objects from '%s': %s", + G_STRFUNC, + source ? e_source_peek_name (source) : "???", + error ? error->message : "Uknown error"); + } + g_clear_error (&error); + return; + } - e_cal_client_get_object_list_sync ( - client, show_sexp, &objects, NULL, &error); + client = E_CAL_CLIENT (source_object); + g_return_if_fail (client != NULL); - if (error != NULL) { - g_warning ( - "%s: Could not get the objects: %s", - G_STRFUNC, error->message); - g_error_free (error); - continue; - } + comp_objects = e_cal_model_get_object_array (model); + g_return_if_fail (comp_objects != NULL); - for (m = objects; m; m = m->next) { - ECalModelComponent *comp_data; - ECalComponentId *id; - ECalComponent *comp = e_cal_component_new (); - - e_cal_component_set_icalcomponent ( - comp, icalcomponent_new_clone (m->data)); - id = e_cal_component_get_id (comp); - - if (!(e_cal_model_get_component_for_uid (model, id))) { - e_table_model_pre_change (E_TABLE_MODEL (model)); - comp_data = g_object_new ( - E_TYPE_CAL_MODEL_COMPONENT, NULL); - comp_data->client = g_object_ref (client); - comp_data->icalcomp = - icalcomponent_new_clone (m->data); - e_cal_model_set_instance_times ( - comp_data, - e_cal_model_get_timezone (model)); - comp_data->dtstart = NULL; - comp_data->dtend = NULL; - comp_data->due = NULL; - comp_data->completed = NULL; - comp_data->color = NULL; - - g_ptr_array_add (comp_objects, comp_data); - e_table_model_row_inserted ( - E_TABLE_MODEL (model), - comp_objects->len - 1); - } - e_cal_component_free_id (id); - g_object_unref (comp); - } + for (m = objects; m; m = m->next) { + ECalModelComponent *comp_data; + ECalComponentId *id; + ECalComponent *comp = e_cal_component_new (); - g_slist_foreach (objects, (GFunc) icalcomponent_free, NULL); - g_slist_free (objects); + e_cal_component_set_icalcomponent ( + comp, icalcomponent_new_clone (m->data)); + id = e_cal_component_get_id (comp); + + if (!(e_cal_model_get_component_for_uid (model, id))) { + e_table_model_pre_change (E_TABLE_MODEL (model)); + comp_data = g_object_new ( + E_TYPE_CAL_MODEL_COMPONENT, NULL); + comp_data->client = g_object_ref (client); + comp_data->icalcomp = + icalcomponent_new_clone (m->data); + e_cal_model_set_instance_times ( + comp_data, + e_cal_model_get_timezone (model)); + comp_data->dtstart = NULL; + comp_data->dtend = NULL; + comp_data->due = NULL; + comp_data->completed = NULL; + comp_data->color = NULL; + + g_ptr_array_add (comp_objects, comp_data); + e_table_model_row_inserted ( + E_TABLE_MODEL (model), + comp_objects->len - 1); + } + e_cal_component_free_id (id); + g_object_unref (comp); } + + e_cal_client_free_icalcomp_slist (objects); } /* Returns the current time, for the ECellDateEdit items. @@ -1806,18 +1835,18 @@ e_task_table_process_completed_tasks (ETaskTable *task_table, gboolean config_changed) { ECalModel *model; - static GMutex *mutex = NULL; + GCancellable *cancellable; gchar *hide_sexp, *show_sexp; - GPtrArray *comp_objects = NULL; - if (!mutex) - mutex = g_mutex_new (); + if (task_table->priv->completed_cancellable) { + g_cancellable_cancel (task_table->priv->completed_cancellable); + g_object_unref (task_table->priv->completed_cancellable); + } - g_mutex_lock (mutex); + task_table->priv->completed_cancellable = g_cancellable_new (); + cancellable = task_table->priv->completed_cancellable; model = e_task_table_get_model (task_table); - comp_objects = e_cal_model_get_object_array (model); - hide_sexp = calendar_config_get_hide_completed_tasks_sexp (TRUE); show_sexp = calendar_config_get_hide_completed_tasks_sexp (FALSE); @@ -1827,15 +1856,16 @@ e_task_table_process_completed_tasks (ETaskTable *task_table, /* Delete rows from model*/ if (hide_sexp) { - hide_completed_rows (model, clients_list, hide_sexp, comp_objects); + task_table_get_object_list_async (clients_list, hide_sexp, cancellable, + hide_completed_rows_ready, model); } /* Insert rows into model */ if (config_changed) { - show_completed_rows (model, clients_list, show_sexp, comp_objects); + task_table_get_object_list_async (clients_list, show_sexp, cancellable, + show_completed_rows_ready, model); } g_free (hide_sexp); g_free (show_sexp); - g_mutex_unlock (mutex); } diff --git a/modules/calendar/e-task-shell-view-private.c b/modules/calendar/e-task-shell-view-private.c index 3467c12190..916494757d 100644 --- a/modules/calendar/e-task-shell-view-private.c +++ b/modules/calendar/e-task-shell-view-private.c @@ -46,14 +46,17 @@ task_shell_view_model_row_appended_cb (ETaskShellView *task_shell_view, e_task_shell_sidebar_add_source (task_shell_sidebar, source); } -static void -task_shell_view_process_completed_tasks (ETaskShellView *task_shell_view) +static gboolean +task_shell_view_process_completed_tasks (gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; ETaskShellSidebar *task_shell_sidebar; ETaskTable *task_table; GList *clients; + task_shell_view->priv->update_completed_timeout = 0; + task_shell_content = task_shell_view->priv->task_shell_content; task_table = e_task_shell_content_get_task_table (task_shell_content); @@ -67,6 +70,18 @@ task_shell_view_process_completed_tasks (ETaskShellView *task_shell_view) e_shell_view_execute_search (E_SHELL_VIEW (task_shell_view)); g_list_free (clients); + + return FALSE; +} + +static void +task_shell_view_schedule_process_completed_tasks (ETaskShellView *task_shell_view) +{ + if (task_shell_view->priv->update_completed_timeout) + g_source_remove (task_shell_view->priv->update_completed_timeout); + + task_shell_view->priv->update_completed_timeout = + g_timeout_add_seconds (1, task_shell_view_process_completed_tasks, task_shell_view); } static void @@ -345,15 +360,15 @@ e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) /* Hide Completed Tasks (enable/units/value) */ g_signal_connect_object ( shell_settings, "notify::cal-hide-completed-tasks", - G_CALLBACK (task_shell_view_process_completed_tasks), + G_CALLBACK (task_shell_view_schedule_process_completed_tasks), task_shell_view, G_CONNECT_SWAPPED); g_signal_connect_object ( shell_settings, "notify::cal-hide-completed-tasks-units", - G_CALLBACK (task_shell_view_process_completed_tasks), + G_CALLBACK (task_shell_view_schedule_process_completed_tasks), task_shell_view, G_CONNECT_SWAPPED); g_signal_connect_object ( shell_settings, "notify::cal-hide-completed-tasks-value", - G_CALLBACK (task_shell_view_process_completed_tasks), + G_CALLBACK (task_shell_view_schedule_process_completed_tasks), task_shell_view, G_CONNECT_SWAPPED); e_task_shell_view_actions_init (task_shell_view); @@ -392,6 +407,11 @@ e_task_shell_view_private_dispose (ETaskShellView *task_shell_view) g_source_remove (priv->update_timeout); priv->update_timeout = 0; } + + if (priv->update_completed_timeout > 0) { + g_source_remove (priv->update_completed_timeout); + priv->update_completed_timeout = 0; + } } void diff --git a/modules/calendar/e-task-shell-view-private.h b/modules/calendar/e-task-shell-view-private.h index ec2173f201..66e664645e 100644 --- a/modules/calendar/e-task-shell-view-private.h +++ b/modules/calendar/e-task-shell-view-private.h @@ -100,6 +100,7 @@ struct _ETaskShellViewPrivate { EActivity *activity; guint update_timeout; + guint update_completed_timeout; guint confirm_purge : 1; }; |