[evolution-data-server] CamelIMAPXJob: Make imapx_job_run() more responsive to cancellations.



commit 28284e3802e95616c36dc64d7d8924829ba7bf37
Author: Matthew Barnes <mbarnes redhat com>
Date:   Thu Dec 1 21:00:16 2011 -0600

    CamelIMAPXJob: Make imapx_job_run() more responsive to cancellations.
    
    Connect a GCancellable::cancelled signal handler that broadcasts the
    GCond that imapx_job_run() is waiting on so it can proceed immediately.
    
    If imapx_job_done() is called sometime later by the thread executing the
    job, the GCond will broadcast again but no one will be listening for it.
    
    Giving CamelIMAPXJob a reference count allows the imapx_job_run() caller
    to drop its job reference and proceed without worrying about whether the
    job is still active in the parser thread, since the parser thread will
    have its own job reference.

 camel/providers/imapx/camel-imapx-server.c |   30 ++++++++++++++++++++++++++++
 1 files changed, 30 insertions(+), 0 deletions(-)
---
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 87aedc4..724785b 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -2255,6 +2255,21 @@ imapx_job_done (CamelIMAPXServer *is,
 	QUEUE_UNLOCK (is);
 }
 
+static void
+imapx_job_cancelled (GCancellable *cancellable,
+                     CamelIMAPXJob *job)
+{
+	/* Unblock imapx_run_job() immediately.
+	 *
+	 * If imapx_job_done() is called sometime later, the
+	 * GCond will broadcast but no one will be listening. */
+
+	g_mutex_lock (job->done_mutex);
+	job->done_flag = TRUE;
+	g_cond_broadcast (job->done_cond);
+	g_mutex_unlock (job->done_mutex);
+}
+
 static gboolean
 imapx_register_job (CamelIMAPXServer *is,
                     CamelIMAPXJob *job,
@@ -2282,11 +2297,20 @@ imapx_run_job (CamelIMAPXServer *is,
                CamelIMAPXJob *job,
                GError **error)
 {
+	gulong cancel_id;
+
 	g_warn_if_fail (job->done_flag == FALSE);
 
 	if (g_cancellable_set_error_if_cancelled (is->cancellable, error))
 		return FALSE;
 
+	if (G_IS_CANCELLABLE (job->cancellable))
+		cancel_id = g_cancellable_connect (
+			job->cancellable,
+			G_CALLBACK (imapx_job_cancelled),
+			imapx_job_ref (job),
+			(GDestroyNotify) imapx_job_unref);
+
 	job->start (is, job);
 
 	if (!job->noreply) {
@@ -2296,6 +2320,12 @@ imapx_run_job (CamelIMAPXServer *is,
 		g_mutex_unlock (job->done_mutex);
 	}
 
+	if (cancel_id > 0)
+		g_cancellable_disconnect (job->cancellable, cancel_id);
+
+	if (g_cancellable_set_error_if_cancelled (job->cancellable, error))
+		return FALSE;
+
 	if (job->error != NULL) {
 		g_propagate_error (error, job->error);
 		job->error = NULL;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]