[anjuta/git-shell] subversion: Replace the dialog mutex hack with a GCond



commit 60823e199815ce329db112cbf0eabfd02317b6e3
Author: James Liggett <jrliggett cox net>
Date:   Tue Aug 3 14:43:39 2010 -0700

    subversion: Replace the dialog mutex hack with a GCond
    
    Get rid of the dialog mutex hacks in SvnCommand and replace them with a GCond.
    Not only was the old way not very consistend, it was also a dirty hack. This
    method is more reliable and a lot cleaner.
    
    Fixes bgo 623751

 plugins/subversion/svn-command.c |  140 ++++++++++++++++++++------------------
 plugins/subversion/svn-command.h |    2 -
 2 files changed, 73 insertions(+), 69 deletions(-)
---
diff --git a/plugins/subversion/svn-command.c b/plugins/subversion/svn-command.c
index d2d131a..1ef4801 100644
--- a/plugins/subversion/svn-command.c
+++ b/plugins/subversion/svn-command.c
@@ -29,39 +29,14 @@ struct _SvnCommandPriv
 	svn_client_ctx_t *client_context;
 	apr_pool_t *pool;
 	GQueue *info_messages;
-	GMutex *ui_lock;
-	gboolean main_thread_has_ui_lock;
+	GCond *dialog_finished_condition;
+	GMutex *dialog_finished_lock;
+	gboolean dialog_finished;
 	gboolean cancelled;
 };
 
 G_DEFINE_TYPE (SvnCommand, svn_command, ANJUTA_TYPE_ASYNC_COMMAND);
 
-static gboolean
-svn_command_acquire_ui_lock (SvnCommand *self)
-{
-	gboolean got_lock;
-	
-	if (!self->priv->main_thread_has_ui_lock)
-	{
-		got_lock = g_mutex_trylock (self->priv->ui_lock);
-		
-		if (got_lock)
-			self->priv->main_thread_has_ui_lock = TRUE;
-		
-		return !got_lock;
-	}
-	else
-		return FALSE;
-}
-
-static gboolean
-svn_command_release_ui_lock (GMutex *ui_lock)
-{
-	g_mutex_unlock (ui_lock);
-	g_mutex_free (ui_lock);
-	
-	return FALSE;
-}
 
 /* Auth functions */
 /* In order to prevent deadlocking when Subversion prompts for something, we
@@ -94,6 +69,41 @@ typedef struct
 	svn_error_t *error;
 } SSLServerTrustArgs;
 
+
+/* Idle destroy functions. The command threads should wait for the dialogs to 
+ * finish before continuing. These functions signals the condition structure,
+ * allowing them to continue. These functions are executed on the main thread */
+
+static void
+on_simple_prompt_finished (SimplePromptArgs *args)
+{
+	SvnCommand *self;
+
+	self = SVN_COMMAND (args->baton);
+	
+	g_mutex_lock (self->priv->dialog_finished_lock);
+	
+	self->priv->dialog_finished = TRUE;
+	g_cond_signal (self->priv->dialog_finished_condition);
+
+	g_mutex_unlock (self->priv->dialog_finished_lock);
+}
+
+static void
+on_ssl_server_trust_prompt_finished (SSLServerTrustArgs *args)
+{
+	SvnCommand *self;
+
+	self = SVN_COMMAND (args->baton);
+	
+	g_mutex_lock (self->priv->dialog_finished_lock);
+	
+	self->priv->dialog_finished = TRUE;
+	g_cond_signal (self->priv->dialog_finished_condition);
+
+	g_mutex_unlock (self->priv->dialog_finished_lock);
+}
+
 static gboolean
 simple_prompt (SimplePromptArgs *args)
 {
@@ -162,10 +172,6 @@ simple_prompt (SimplePromptArgs *args)
 	gtk_widget_destroy (svn_user_auth);
 	args->error = err;
 	
-	/* Release because main thread should already have the lock */
-	svn_command = SVN_COMMAND (args->baton);
-	svn_command_unlock_ui (svn_command);
-	
 	return FALSE;
 }
 
@@ -228,10 +234,6 @@ ssl_server_trust_prompt (SSLServerTrustArgs *args)
 	gtk_widget_destroy (svn_server_trust);
 	args->error = err;
 	
-	/* Release because main thread should already have the lock */
-	svn_command = SVN_COMMAND (args->baton);
-	svn_command_unlock_ui (svn_command);
-	
 	return FALSE;
 }
 
@@ -244,7 +246,7 @@ svn_auth_simple_prompt_func_cb (svn_auth_cred_simple_t **cred, void *baton,
 	SimplePromptArgs *args;
 	SvnCommand *svn_command;
 	svn_error_t *error;
-	
+
 	args = g_new0 (SimplePromptArgs, 1);
 	args->cred = cred;
 	args->baton = baton;
@@ -255,15 +257,27 @@ svn_auth_simple_prompt_func_cb (svn_auth_cred_simple_t **cred, void *baton,
 	
 	svn_command = SVN_COMMAND (baton);
 	
-	g_idle_add ((GSourceFunc) simple_prompt, args);
+	/* Wait for the dialog to finish */
+	g_mutex_lock (svn_command->priv->dialog_finished_lock);
 	
-	svn_command_lock_ui (svn_command);
-	svn_command_unlock_ui (svn_command);
+	svn_command->priv->dialog_finished = FALSE;
+
+	g_idle_add_full (G_PRIORITY_HIGH_IDLE,
+					 (GSourceFunc) simple_prompt, args, 
+	                 (GDestroyNotify) on_simple_prompt_finished);
+
+	while (!svn_command->priv->dialog_finished)
+	{
+		g_cond_wait (svn_command->priv->dialog_finished_condition, 
+		             svn_command->priv->dialog_finished_lock);
+	}
 	
 	error = args->error;
 	g_free (args->realm);
 	g_free (args->username);
 	g_free (args);
+
+	g_mutex_unlock (svn_command->priv->dialog_finished_lock);
 	
 	return error;
 
@@ -292,17 +306,28 @@ svn_auth_ssl_server_trust_prompt_func_cb (svn_auth_cred_ssl_server_trust_t **cre
 	args->pool = pool;
 	
 	svn_command = SVN_COMMAND (baton);
+
+	/* Wait for the dialog to finish */
+	g_mutex_lock (svn_command->priv->dialog_finished_lock);
 	
+	svn_command->priv->dialog_finished = FALSE;
+
 	g_idle_add_full (G_PRIORITY_HIGH_IDLE,
-					 (GSourceFunc) ssl_server_trust_prompt, args, NULL);
-	
-	svn_command_lock_ui (svn_command);
-	svn_command_unlock_ui (svn_command);
+					 (GSourceFunc) ssl_server_trust_prompt, args, 
+	                 (GDestroyNotify) on_ssl_server_trust_prompt_finished);
+
+	while (!svn_command->priv->dialog_finished)
+	{
+		g_cond_wait (svn_command->priv->dialog_finished_condition, 
+		             svn_command->priv->dialog_finished_lock);
+	}
 	
 	error = args->error;
 	g_free (args->realm);
 	g_free (args->cert_info);
 	g_free (args);
+
+	g_mutex_unlock (svn_command->priv->dialog_finished_lock);
 	
 	return error;
 }
@@ -467,10 +492,8 @@ svn_command_init (SvnCommand *self)
 						   self->priv->pool);
 	
 	self->priv->info_messages = g_queue_new ();
-	self->priv->ui_lock = g_mutex_new ();
-	
-	/* Make sure that the main thread holds the lock */
-	g_idle_add ((GSourceFunc) svn_command_acquire_ui_lock, self);
+	self->priv->dialog_finished_lock = g_mutex_new ();
+	self->priv->dialog_finished_condition = g_cond_new ();
 	
 	/* Fill in the auth baton callbacks */
 	providers = apr_array_make (self->priv->pool, 1, 
@@ -551,7 +574,8 @@ svn_command_finalize (GObject *object)
 		current_message_line = g_list_next (current_message_line);
 	}
 	
-	g_idle_add ((GSourceFunc) svn_command_release_ui_lock, self->priv->ui_lock);
+	g_mutex_free (self->priv->dialog_finished_lock);
+	g_cond_free (self->priv->dialog_finished_condition);
 	
 	g_queue_free (self->priv->info_messages);
 	g_free (self->priv);
@@ -635,24 +659,6 @@ svn_command_get_pool (SvnCommand *self)
 	return self->priv->pool;
 }
 
-void
-svn_command_lock_ui (SvnCommand *self)
-{
-	g_mutex_lock (self->priv->ui_lock);
-	
-	/* Have the main thread acquire the lock as soon as the other thread is done
-	 * with it. The main thread should *not* acqure the lock, only release 
-	 * it. */
-	self->priv->main_thread_has_ui_lock = FALSE;
-	g_idle_add ((GSourceFunc) svn_command_acquire_ui_lock, self);
-}
-
-void
-svn_command_unlock_ui (SvnCommand *self)
-{
-	g_mutex_unlock (self->priv->ui_lock);
-}
-
 gchar *
 svn_command_make_canonical_path (SvnCommand *self, const gchar *path)
 {
diff --git a/plugins/subversion/svn-command.h b/plugins/subversion/svn-command.h
index 9f003fe..c060f85 100644
--- a/plugins/subversion/svn-command.h
+++ b/plugins/subversion/svn-command.h
@@ -64,8 +64,6 @@ GQueue * svn_command_get_info_queue (SvnCommand *self);
 void svn_command_set_error (SvnCommand *self, svn_error_t *error);
 svn_client_ctx_t *svn_command_get_client_context (SvnCommand *self);
 apr_pool_t *svn_command_get_pool (SvnCommand *self);
-void svn_command_lock_ui (SvnCommand *self);
-void svn_command_unlock_ui (SvnCommand *self);
 gchar *svn_command_make_canonical_path (SvnCommand *self, const gchar *path);
 
 /* Static methods */



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