[anjuta] git: Don't allow multiple status commands to run concurrently



commit be037c2dbdbae2eae403db348e2beb97bea6103d
Author: James Liggett <jrliggett cox net>
Date:   Thu Aug 6 22:59:50 2009 -0700

    git: Don't allow multiple status commands to run concurrently
    
    Git acquires a lock on the repository when a command runs, so running status commands
    concurrently shows race condition-like behavior when setting status icons in the file manager.
    
    However, the icons show up a lot slower with this patch; changes to the file manager may be
    needed.

 libanjuta/Makefile.am            |    7 ++-
 libanjuta/anjuta-command-queue.c |  111 ++++++++++++++++++++++++++++++++++++++
 libanjuta/anjuta-command-queue.h |   58 ++++++++++++++++++++
 plugins/git/git-vcs-interface.c  |    3 +-
 plugins/git/plugin.c             |    3 +
 plugins/git/plugin.h             |    2 +
 6 files changed, 181 insertions(+), 3 deletions(-)
---
diff --git a/libanjuta/Makefile.am b/libanjuta/Makefile.am
index 7cc7d71..5251aee 100644
--- a/libanjuta/Makefile.am
+++ b/libanjuta/Makefile.am
@@ -79,7 +79,9 @@ libanjuta_la_SOURCES= \
 	anjuta-debug.c \
 	anjuta-debug.h \
 	gbf-project.c \
-	gbf-project.h
+	gbf-project.h \
+	anjuta-command-queue.c \
+	anjuta-command-queue.h
 
 if HAVE_PLUGIN_GLADE
 
@@ -137,7 +139,8 @@ libanjuta_include = \
 	anjuta-async-notify.h \
 	anjuta-sync-command.h \
 	anjuta-version.h \
-	gbf-project.h
+	gbf-project.h \
+	anjuta-command-queue.h
 
 libanjutainclude_HEADERS = \
 	$(libanjuta_include) \
diff --git a/libanjuta/anjuta-command-queue.c b/libanjuta/anjuta-command-queue.c
new file mode 100644
index 0000000..d7da3fb
--- /dev/null
+++ b/libanjuta/anjuta-command-queue.c
@@ -0,0 +1,111 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) James Liggett 2009 <jrliggett cox net>
+ * 
+ * anjuta is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * anjuta is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "anjuta-command-queue.h"
+
+struct _AnjutaCommandQueuePriv
+{
+	GQueue *queue;
+	gboolean busy;
+};
+
+G_DEFINE_TYPE (AnjutaCommandQueue, anjuta_command_queue, G_TYPE_OBJECT);
+
+static void
+anjuta_command_queue_init (AnjutaCommandQueue *self)
+{
+	self->priv = g_new0 (AnjutaCommandQueuePriv, 1);
+
+	self->priv->queue = g_queue_new ();
+}
+
+static void
+anjuta_command_queue_finalize (GObject *object)
+{
+	AnjutaCommandQueue *self;
+	GList *current_command;
+
+	self = ANJUTA_COMMAND_QUEUE (object);
+
+	current_command = self->priv->queue->head;
+
+	while (current_command)
+	{
+		g_object_unref (current_command->data);
+		current_command = g_list_next (current_command);
+	}
+
+	g_queue_free (self->priv->queue);
+	g_free (self->priv);
+
+	G_OBJECT_CLASS (anjuta_command_queue_parent_class)->finalize (object);
+}
+
+static void
+anjuta_command_queue_class_init (AnjutaCommandQueueClass *klass)
+{
+	GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = anjuta_command_queue_finalize;
+}
+
+static void
+on_command_finished (AnjutaCommand *command, guint return_code,
+                     AnjutaCommandQueue *self)
+{
+	AnjutaCommand *next_command;
+
+	next_command = g_queue_pop_head (self->priv->queue);
+
+	if (next_command)
+	{
+		g_signal_connect (G_OBJECT (next_command), "command-finished",
+		                  G_CALLBACK (on_command_finished),
+		                  self);
+
+		anjuta_command_start (next_command);
+
+		g_object_unref (next_command);
+	}
+	else
+		self->priv->busy = FALSE;
+}
+
+AnjutaCommandQueue *
+anjuta_command_queue_new (void)
+{
+	return g_object_new (ANJUTA_TYPE_COMMAND_QUEUE, NULL);
+}
+
+void
+anjuta_command_queue_push (AnjutaCommandQueue *self, AnjutaCommand *command)
+{
+	if (!self->priv->busy)
+	{
+		self->priv->busy = TRUE;
+
+		g_signal_connect (G_OBJECT (command), "command-finished",
+		                  G_CALLBACK (on_command_finished),
+		                  self);
+		
+		anjuta_command_start (command);
+	}
+	else
+		g_queue_push_tail (self->priv->queue, g_object_ref (command));
+}
diff --git a/libanjuta/anjuta-command-queue.h b/libanjuta/anjuta-command-queue.h
new file mode 100644
index 0000000..a10b07e
--- /dev/null
+++ b/libanjuta/anjuta-command-queue.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) James Liggett 2009 <jrliggett cox net>
+ * 
+ * anjuta is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * anjuta is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ANJUTA_COMMAND_QUEUE_H_
+#define _ANJUTA_COMMAND_QUEUE_H_
+
+#include <glib-object.h>
+#include "anjuta-command.h"
+
+G_BEGIN_DECLS
+
+#define ANJUTA_TYPE_COMMAND_QUEUE             (anjuta_command_queue_get_type ())
+#define ANJUTA_COMMAND_QUEUE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANJUTA_TYPE_COMMAND_QUEUE, AnjutaCommandQueue))
+#define ANJUTA_COMMAND_QUEUE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), ANJUTA_TYPE_COMMAND_QUEUE, AnjutaCommandQueueClass))
+#define ANJUTA_IS_COMMAND_QUEUE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANJUTA_TYPE_COMMAND_QUEUE))
+#define ANJUTA_IS_COMMAND_QUEUE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), ANJUTA_TYPE_COMMAND_QUEUE))
+#define ANJUTA_COMMAND_QUEUE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), ANJUTA_TYPE_COMMAND_QUEUE, AnjutaCommandQueueClass))
+
+typedef struct _AnjutaCommandQueueClass AnjutaCommandQueueClass;
+typedef struct _AnjutaCommandQueue AnjutaCommandQueue;
+typedef struct _AnjutaCommandQueuePriv AnjutaCommandQueuePriv;
+
+struct _AnjutaCommandQueueClass
+{
+	GObjectClass parent_class;
+};
+
+struct _AnjutaCommandQueue
+{
+	GObject parent_instance;
+
+	AnjutaCommandQueuePriv *priv;
+};
+
+GType anjuta_command_queue_get_type (void) G_GNUC_CONST;
+AnjutaCommandQueue * anjuta_command_queue_new (void);
+void anjuta_command_queue_push (AnjutaCommandQueue *self, 
+                                AnjutaCommand *command);
+
+G_END_DECLS
+
+#endif /* _ANJUTA_COMMAND_QUEUE_H_ */
diff --git a/plugins/git/git-vcs-interface.c b/plugins/git/git-vcs-interface.c
index 56f9c10..f0e81ee 100644
--- a/plugins/git/git-vcs-interface.c
+++ b/plugins/git/git-vcs-interface.c
@@ -269,7 +269,8 @@ git_ivcs_query_status (IAnjutaVcs *obj, GFile *file,
 		                          notify);
 	}
 
-	anjuta_command_start (ANJUTA_COMMAND (status_command));
+	anjuta_command_queue_push (ANJUTA_PLUGIN_GIT (obj)->command_queue,
+	                           ANJUTA_COMMAND (status_command));
 }
 
 void 
diff --git a/plugins/git/plugin.c b/plugins/git/plugin.c
index 9130449..ca19be6 100644
--- a/plugins/git/plugin.c
+++ b/plugins/git/plugin.c
@@ -778,6 +778,8 @@ git_activate_plugin (AnjutaPlugin *plugin)
 									git_plugin->stash_widget_grip,
 									ANJUTA_SHELL_PLACEMENT_LEFT,
 									NULL);
+
+	git_plugin->command_queue = anjuta_command_queue_new ();
 	
 	/* Add watches */
 	git_plugin->project_root_watch_id = anjuta_plugin_add_watch (plugin,
@@ -842,6 +844,7 @@ git_deactivate_plugin (AnjutaPlugin *plugin)
 	g_free (git_plugin->project_root_directory);
 	g_free (git_plugin->current_editor_filename);
 	g_free (git_plugin->current_fm_filename);
+	g_object_unref (git_plugin->command_queue);
 	
 	anjuta_shell_remove_widget (plugin->shell, git_plugin->log_viewer, NULL);
 	anjuta_shell_remove_widget (plugin->shell, git_plugin->stash_widget, NULL);
diff --git a/plugins/git/plugin.h b/plugins/git/plugin.h
index b04fb24..7f4ee73 100644
--- a/plugins/git/plugin.h
+++ b/plugins/git/plugin.h
@@ -31,6 +31,7 @@
 #include <libanjuta/interfaces/ianjuta-file-manager.h>
 #include <libanjuta/anjuta-shell.h>
 #include <libanjuta/anjuta-debug.h>
+#include <libanjuta/anjuta-command-queue.h>
 
 extern GType git_get_type (GTypeModule *module);
 #define ANJUTA_TYPE_PLUGIN_GIT         (git_get_type (NULL))
@@ -55,6 +56,7 @@ struct _Git
 	gchar *current_editor_filename;
 	gchar *current_fm_filename;
 	IAnjutaMessageView *message_view;
+	AnjutaCommandQueue *command_queue;
 	
 	/* Watches */
 	gint project_root_watch_id;



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