summaryrefslogtreecommitdiff
path: root/src/gtkext
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2009-09-20 13:22:53 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2009-09-20 13:22:53 (GMT)
commitf7c1c34cb54b239586bf431b1749759baee9493e (patch)
tree24b2954e45202bcc36f60166112a23acf931be1f /src/gtkext
parent859bdb6b51d76058eb1a8bfa619a15978f50b251 (diff)
Rewritten the work queue and fixed thread concurrency.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@117 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/gtkext')
-rw-r--r--src/gtkext/gtkbinview-int.h4
-rw-r--r--src/gtkext/gtkbinview.c8
-rw-r--r--src/gtkext/gtkblockview.c326
-rw-r--r--src/gtkext/gtkgraphview.c80
4 files changed, 346 insertions, 72 deletions
diff --git a/src/gtkext/gtkbinview-int.h b/src/gtkext/gtkbinview-int.h
index 0e38c57..e785bab 100644
--- a/src/gtkext/gtkbinview-int.h
+++ b/src/gtkext/gtkbinview-int.h
@@ -66,6 +66,10 @@ struct _GtkBinViewClass
{
GtkFixedClass parent; /* A laisser en premier */
+ /* Signaux */
+
+ void (* lines_set) (GtkBinView *);
+
};
diff --git a/src/gtkext/gtkbinview.c b/src/gtkext/gtkbinview.c
index 696799b..147a59c 100644
--- a/src/gtkext/gtkbinview.c
+++ b/src/gtkext/gtkbinview.c
@@ -68,6 +68,14 @@ static void gtk_binview_class_init(GtkBinViewClass *class)
widget_class->realize = gtk_bin_view_realize;
widget_class->expose_event = gtk_bin_view_expose;
+ g_signal_new("lines-set",
+ GTK_TYPE_BIN_VIEW,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkBinViewClass, lines_set),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
}
diff --git a/src/gtkext/gtkblockview.c b/src/gtkext/gtkblockview.c
index 23f86ce..ac06af3 100644
--- a/src/gtkext/gtkblockview.c
+++ b/src/gtkext/gtkblockview.c
@@ -35,10 +35,63 @@
#include "support.h"
#include "../analysis/exporter.h"
#include "../common/dllist.h"
+#include "../glibext/delayed-int.h"
-#define MARGIN_SPACE 4 /* TODO : delete me ! */
+#ifndef _
+# define _(str) str
+#endif
+
+
+
+
+/* -------------------------- INSERTION DIFFEREE DE LIGNES -------------------------- */
+
+
+#define G_TYPE_DELAYED_INSERTION g_delayed_insertion_get_type()
+#define G_DELAYED_INSERTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_insertion_get_type(), GDelayedInsertion))
+#define G_IS_DELAYED_INSERTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_insertion_get_type()))
+#define G_DELAYED_INSERTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_INSERTION, GDelayedInsertionClass))
+#define G_IS_DELAYED_INSERTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_INSERTION))
+#define G_DELAYED_INSERTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_INSERTION, GDelayedInsertionClass))
+
+
+/* Ensembles binaires à désassembler (instance) */
+typedef struct _GDelayedInsertion
+{
+ GDelayedWork parent; /* A laisser en premier */
+
+ GtkBlockView *view; /* Visualisation à constituer */
+
+ size_t lengths[SAR_COUNT]; /* Différentes tailles de zone */
+
+} GDelayedInsertion;
+
+/* Ensembles binaires à désassembler (classe) */
+typedef struct _GDelayedInsertionClass
+{
+ GDelayedWorkClass parent; /* A laisser en premier */
+
+} GDelayedInsertionClass;
+
+
+/* Indique le type défini pour les tâches d'insertions différées. */
+static GType g_delayed_insertion_get_type(void);
+
+/* Initialise la classe des tâches d'insertions différées. */
+static void g_delayed_insertion_class_init(GDelayedInsertionClass *);
+
+/* Initialise une tâche d'insertions différées. */
+static void g_delayed_insertion_init(GDelayedInsertion *);
+
+/* Crée une tâche d'insertions différées. */
+static GDelayedInsertion *g_delayed_insertion_new(GtkBlockView *);
+
+/* Assure des insertion de lignes en différé. */
+static void g_delayed_insertion_process(GDelayedInsertion *, GtkExtStatusBar *);
+
+
@@ -76,6 +129,8 @@ struct _GtkBlockViewClass
+
+
static void
gtk_text_view2_set_attributes_from_style (GtkTextAttributes *values,
GtkStyle *style)
@@ -108,6 +163,8 @@ static void gtk_block_view_realize(GtkWidget *);
/* Définit les lignes du bloc de représentation. */
static void gtk_block_view_set_rendering_lines(GtkBlockView *, GRenderingLine *, GRenderingLine *);
+/* Achève la construction de la visualisation des lignes. */
+static void gtk_block_view_complete_building_content(GDelayedInsertion *, GtkBlockView *);
@@ -150,6 +207,171 @@ static void gtk_block_view_destroy(GtkObject *object);
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INSERTION DIFFEREE DE LIGNES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour les tâches d'insertions différées. */
+G_DEFINE_TYPE(GDelayedInsertion, g_delayed_insertion, G_TYPE_DELAYED_WORK);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des tâches d'insertions différées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_insertion_class_init(GDelayedInsertionClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : insertion = instance à initialiser. *
+* *
+* Description : Initialise une tâche d'insertions différées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_insertion_init(GDelayedInsertion *insertion)
+{
+ G_DELAYED_WORK(insertion)->run = (run_task_fc)g_delayed_insertion_process;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : view = visualisation de lignes à constituer. *
+* *
+* Description : Crée une tâche d'insertions différées. *
+* *
+* Retour : Tâche créée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GDelayedInsertion *g_delayed_insertion_new(GtkBlockView *view)
+{
+ GDelayedInsertion *result; /* Tâche à retourner */
+
+ result = g_object_new(G_TYPE_DELAYED_INSERTION, NULL);
+
+ result->view = view;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : insertion = insertions de lignes à mener. *
+* statusbar = barre de statut à tenir informée. *
+* *
+* Description : Assure des insertion de lignes en différé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_insertion_process(GDelayedInsertion *insertion, GtkExtStatusBar *statusbar)
+{
+ GtkBlockView *view; /* Visualisation à constituer */
+ GRenderingLine *lines; /* Liste de lignes à intégrer */
+ GRenderingLine *last; /* Dernière ligne ou NULL */
+ vmpa_t start; /* Adresse de début de parcours*/
+ vmpa_t end; /* Adresse de fin de parcours */
+ guint id; /* Identifiant de statut */
+ GRenderingLine *iter; /* Boucle de parcours */
+ GtkTextIter pos; /* Point d'insertion */
+ GtkTextMark *mark; /* Marquage de ligne associée */
+ vmpa_t done; /* Quantité déjà parcourue */
+
+ view = insertion->view;
+
+ lines = GTK_BIN_VIEW(view)->lines;
+ last = GTK_BIN_VIEW(view)->last;
+
+ iter = g_rendering_line_loop_for_code(lines, last);
+ start = get_rendering_line_address(lines);
+
+ iter = g_rendering_line_get_last_iter(lines, last);
+ end = get_rendering_line_address(iter) + get_rendering_line_length(iter) - start;
+
+ insertion->lengths[SAR_ADDRESS] = 0;
+ insertion->lengths[SAR_CODE] = 0;
+ insertion->lengths[SAR_INSTRUCTION] = 0;
+
+ id = gtk_extended_status_bar_push(statusbar, _("Inserting lines..."), true);
+
+ for (iter = lines;
+ iter != NULL;
+ iter = g_rendering_line_get_next_iter(lines, iter, last))
+ {
+ g_signal_connect(iter, "rendering-line-flags-changed",
+ G_CALLBACK(gtk_block_view_update_margin), view);
+
+ gdk_threads_enter();
+
+ if (iter != lines)
+ {
+ gtk_text_buffer_get_end_iter(view->buffer, &pos);
+ gtk_text_buffer_insert_with_tags(view->buffer, &pos, "\n", 1, NULL);
+ }
+
+ gtk_text_buffer_get_end_iter(view->buffer, &pos);
+
+ mark = gtk_text_buffer_create_mark(view->buffer, NULL, &pos, TRUE);
+ g_object_set_data(G_OBJECT(mark), "line", iter);
+
+ g_content_exporter_add_to_gtk_buffer(G_CONTENT_EXPORTER(iter), view->rendering,
+ view->buffer, &pos, insertion->lengths);
+
+ gdk_flush ();
+ gdk_threads_leave();
+
+ done = get_rendering_line_address(iter) + get_rendering_line_length(iter) - start;
+ gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / end);
+
+ }
+
+ gtk_extended_status_bar_remove(statusbar, id);
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/* Détermine le type du composant d'affichage en block. */
G_DEFINE_TYPE(GtkBlockView, gtk_block_view, GTK_TYPE_BIN_VIEW)
@@ -571,43 +793,6 @@ static gboolean gtk_block_view_expose(GtkWidget *widget, GdkEventExpose *event)
/* Impression du désassemblage */
-
-#if 0
- gdk_window_begin_paint_region(GDK_DRAWABLE(widget->window), event->region);
-
- gdk_gc_set_clip_region(bview->gc, event->region);
-
- gdk_gc_get_values(bview->gc, &values);
-
- gdk_color_white(gtk_widget_get_colormap(widget), &white);
- gdk_gc_set_foreground(bview->gc, &white);
-
- gtk_widget_get_size_request(widget, &width, &height);
-
- gdk_draw_rectangle(GDK_DRAWABLE(widget->window), bview->gc,
- TRUE, 0, 0, width, height);
-
- gdk_gc_set_foreground(bview->gc, &values.foreground);
- /*
- y = event->area.y;
- iter = g_rendering_line_find_by_y(bview->lines, bview->last, &y);
-
- y = event->area.y - y;
-
- for ( ; iter != NULL && y < (event->area.y + event->area.height);
- iter = g_rendering_line_get_next_iter(bview->lines, iter, bview->last))
- {
- g_rendering_line_draw(iter, GDK_DRAWABLE(widget->window), bview->gc,
- MARGIN_SPACE, 2 * MARGIN_SPACE + GTK_BLOCK_VIEW(bview)->line_height,
- y, GTK_BLOCK_VIEW(bview)->line_height, GTK_BLOCK_VIEW(bview)->rendering);
-
- y += GTK_BLOCK_VIEW(bview)->line_height;
-
- }
- */
- gdk_window_end_paint(GDK_DRAWABLE(widget->window));
-#endif
-
gtk_text_layout_set_screen_width (GTK_BLOCK_VIEW(bview)->layout,
MAX (1, 1000));
@@ -730,40 +915,48 @@ void gtk_block_view_set_format(GtkBlockView *view, const exe_format *format)
static void gtk_block_view_set_rendering_lines(GtkBlockView *view, GRenderingLine *lines, GRenderingLine *last)
{
- size_t lengths[SAR_COUNT]; /* Différentes tailles de zone */
- GRenderingLine *iter; /* Boucle de parcours */
- GtkTextIter pos; /* Point d'insertion */
- GtkTextMark *mark; /* Marquage de ligne associée */
- PangoTabArray *tabs; /* Tailles de tabulation */
- GdkRectangle rect; /* Zone d'un point */
+ GWorkQueue *queue; /* Gestionnaire de différés */
+ GDelayedInsertion *insertion; /* Insertions à mener */
- lengths[SAR_ADDRESS] = 0;
- lengths[SAR_CODE] = 0;
- lengths[SAR_INSTRUCTION] = 0;
+ queue = get_work_queue();
- for (iter = GTK_BIN_VIEW(view)->lines;
- iter != NULL;
- iter = g_rendering_line_get_next_iter(GTK_BIN_VIEW(view)->lines, iter, GTK_BIN_VIEW(view)->last))
- {
- g_signal_connect(iter, "rendering-line-flags-changed",
- G_CALLBACK(gtk_block_view_update_margin), view);
+ insertion = g_delayed_insertion_new(view);
- if (iter != GTK_BIN_VIEW(view)->lines)
- {
- gtk_text_buffer_get_end_iter(view->buffer, &pos);
- gtk_text_buffer_insert_with_tags(view->buffer, &pos, "\n", 1, NULL);
- }
+ g_signal_connect(insertion, "work-completed",
+ G_CALLBACK(gtk_block_view_complete_building_content), view);
- gtk_text_buffer_get_end_iter(view->buffer, &pos);
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(insertion));
- mark = gtk_text_buffer_create_mark(view->buffer, NULL, &pos, TRUE);
- g_object_set_data(G_OBJECT(mark), "line", iter);
+}
- g_content_exporter_add_to_gtk_buffer(G_CONTENT_EXPORTER(iter), view->rendering,
- view->buffer, &pos, lengths);
- }
+/******************************************************************************
+* *
+* Paramètres : insertion = travail d'insertion effectué. *
+* view = composant GTK à mettre à jour. *
+* *
+* Description : Achève la construction de la visualisation des lignes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_block_view_complete_building_content(GDelayedInsertion *insertion, GtkBlockView *view)
+{
+ size_t lengths[SAR_COUNT]; /* Différentes tailles de zone */
+ GtkTextIter pos; /* Point d'insertion */
+ PangoTabArray *tabs; /* Tailles de tabulation */
+ GdkRectangle rect; /* Zone d'un point */
+
+ lengths[SAR_ADDRESS] = insertion->lengths[SAR_ADDRESS];
+ lengths[SAR_CODE] = insertion->lengths[SAR_CODE];
+ lengths[SAR_INSTRUCTION] = insertion->lengths[SAR_INSTRUCTION];
+ gdk_threads_enter();
+
+ gtk_text_buffer_get_end_iter(view->buffer, &pos);
gtk_text_layout_move_iter_visually(view->layout, &pos, -1);
gtk_text_layout_get_iter_location(view->layout, &pos, &rect);
@@ -808,6 +1001,11 @@ static void gtk_block_view_set_rendering_lines(GtkBlockView *view, GRenderingLin
gtk_block_view_recompute_size_request(view);
+ gdk_flush ();
+ gdk_threads_leave();
+
+ g_signal_emit_by_name(view, "lines-set");
+
}
diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c
index cc2d930..d62cc33 100644
--- a/src/gtkext/gtkgraphview.c
+++ b/src/gtkext/gtkgraphview.c
@@ -45,6 +45,10 @@ struct _GtkGraphView
GtkBinView **childs; /* Liste des sous-blocs */
size_t childs_count; /* Taille de cette liste */
+ size_t ready; /* Construction complète */
+ GMutex *mutex; /* Accès à la variable */
+ GCond *cond; /* Attente de changement */
+
GtkLinkRenderer **links; /* Liste des liens graphiques */
size_t links_count; /* Nombre de ces liens */
@@ -80,7 +84,10 @@ static void gtk_graph_view_define_main_address(GtkGraphView *, vmpa_t);
static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *, vmpa_t, gint *, gint *);
/* Définit la liste complète des éléments du futur graphique. */
-static GtkBinView **gtk_graph_view_load_nodes(GOpenidaBinary *, GRenderingLine *, GRenderingLine *, size_t *);
+static GtkBinView **gtk_graph_view_load_nodes(GtkGraphView *, GOpenidaBinary *, GRenderingLine *, GRenderingLine *);
+
+/* Prend note de la fin d'une construction d'une visualisation. */
+static void notify_graph_view(GtkBinView *, GtkGraphView *);
/* Détermine le type du composant d'affichage en graphique. */
@@ -132,6 +139,9 @@ static void gtk_graph_view_init(GtkGraphView *view)
binview->define_address = (define_main_address_fc)gtk_graph_view_define_main_address;
binview->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates;
+ view->mutex = g_mutex_new();
+ view->cond = g_cond_new();
+
}
@@ -255,6 +265,8 @@ static void gtk_graph_view_set_rendering_lines(GtkGraphView *view, GRenderingLin
{
gtk_graph_view_reset(view);
+ g_signal_emit_by_name(view, "lines-set");
+
}
@@ -308,7 +320,7 @@ static void gtk_graph_view_define_main_address(GtkGraphView *view, vmpa_t addr)
first = g_rendering_line_find_by_address(GTK_BIN_VIEW(view)->lines, GTK_BIN_VIEW(view)->last, start);
last = g_rendering_line_find_by_address(GTK_BIN_VIEW(view)->lines, GTK_BIN_VIEW(view)->last, end - 1);
- view->childs = gtk_graph_view_load_nodes(GTK_BIN_VIEW(view)->binary, first, last, &view->childs_count);
+ view->childs = gtk_graph_view_load_nodes(view, GTK_BIN_VIEW(view)->binary, first, last);
build_graph_view(GTK_FIXED(view), view->childs, view->childs_count);
@@ -363,10 +375,10 @@ static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *view, vmp
/******************************************************************************
* *
-* Paramètres : binary = contenu binaire à l'origine des lignes. *
+* Paramètres : view = composant d'affichage GTK à mettre à jour. *
+* binary = contenu binaire à l'origine des lignes. *
* first = première ligne à analyser. *
* last = dernière ligne à analyser. *
-* count = nombre d'éléments créés. [OUT] *
* *
* Description : Définit la liste complète des éléments du futur graphique. *
* *
@@ -376,16 +388,28 @@ static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *view, vmp
* *
******************************************************************************/
-static GtkBinView **gtk_graph_view_load_nodes(GOpenidaBinary *binary, GRenderingLine *first, GRenderingLine *last, size_t *count)
+static GtkBinView **gtk_graph_view_load_nodes(GtkGraphView *view, GOpenidaBinary *binary, GRenderingLine *first, GRenderingLine *last)
{
GtkBinView **result; /* Liste à retourner */
+ size_t *count; /* Nombre d'éléments créés. */
GRenderingLine *begin; /* Début d'un groupe de lignes */
GRenderingLine *end; /* Fin d'un groupe de lignes */
GRenderingLine *iter; /* Boucle de parcours */
result = NULL;
+
+ view->ready = 0;
+
+ count = &view->childs_count;
*count = 0;
+ /**
+ * Comme la fonction est appelée depuis un événement et utilise des threads et GTK,
+ * on doit lever temporairement le verrou GDK.
+ */
+ gdk_flush ();
+ gdk_threads_leave();
+
begin = NULL;
for (iter = first; iter != NULL; iter = g_rendering_line_get_next_iter(first, iter, last))
@@ -395,7 +419,8 @@ static GtkBinView **gtk_graph_view_load_nodes(GOpenidaBinary *binary, GRendering
result = (GtkBinView **)realloc(result, ++(*count) * sizeof(GtkBinView *));
result[*count - 1] = GTK_BIN_VIEW(gtk_block_view_new(MRD_GRAPH));
- gtk_widget_show(GTK_WIDGET(result[*count - 1]));
+
+ g_signal_connect(result[*count - 1], "lines-set", G_CALLBACK(notify_graph_view), view);
gtk_bin_view_show_border(result[*count - 1], true);
gtk_bin_view_set_rendering_lines(result[*count - 1], binary, begin, end);
@@ -412,7 +437,8 @@ static GtkBinView **gtk_graph_view_load_nodes(GOpenidaBinary *binary, GRendering
result = (GtkBinView **)realloc(result, ++(*count) * sizeof(GtkBinView *));
result[*count - 1] = GTK_BIN_VIEW(gtk_block_view_new(MRD_GRAPH));
- gtk_widget_show(GTK_WIDGET(result[*count - 1]));
+
+ g_signal_connect(result[*count - 1], "lines-set", G_CALLBACK(notify_graph_view), view);
gtk_bin_view_show_border(result[*count - 1], true);
gtk_bin_view_set_rendering_lines(result[*count - 1], binary, begin, end);
@@ -428,13 +454,22 @@ static GtkBinView **gtk_graph_view_load_nodes(GOpenidaBinary *binary, GRendering
result = (GtkBinView **)realloc(result, ++(*count) * sizeof(GtkBinView *));
result[*count - 1] = GTK_BIN_VIEW(gtk_block_view_new(MRD_GRAPH));
- gtk_widget_show(GTK_WIDGET(result[*count - 1]));
+
+ g_signal_connect(result[*count - 1], "lines-set", G_CALLBACK(notify_graph_view), view);
gtk_bin_view_show_border(result[*count - 1], true);
gtk_bin_view_set_rendering_lines(result[*count - 1], binary, begin, end);
}
+ /* Attente de la fin de construction */
+ g_mutex_lock(view->mutex);
+ while (view->ready < *count)
+ g_cond_wait(view->cond, view->mutex);
+ g_mutex_unlock(view->mutex);
+
+ gdk_threads_enter();
+
return result;
@@ -443,6 +478,35 @@ static GtkBinView **gtk_graph_view_load_nodes(GOpenidaBinary *binary, GRendering
/******************************************************************************
* *
+* Paramètres : view = composant d'affichage prêt à utilisation. *
+* parent = composant d'affichage supérieur. *
+* *
+* Description : Prend note de la fin d'une construction d'une visualisation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void notify_graph_view(GtkBinView *view, GtkGraphView *parent)
+{
+ g_mutex_lock(parent->mutex);
+
+ parent->ready++;
+
+ g_cond_signal(parent->cond);
+ g_mutex_unlock(parent->mutex);
+
+ g_signal_handlers_disconnect_by_func(view, G_CALLBACK(notify_graph_view), parent);
+
+ gtk_widget_show(GTK_WIDGET(view));
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : view = composant GTK à mettre à jour. *
* links = liens graphiques entre les blocs à intégrer. *
* count = quantité de ces liens graphiques. *