diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2009-09-20 13:22:53 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2009-09-20 13:22:53 (GMT) |
commit | f7c1c34cb54b239586bf431b1749759baee9493e (patch) | |
tree | 24b2954e45202bcc36f60166112a23acf931be1f /src/gtkext | |
parent | 859bdb6b51d76058eb1a8bfa619a15978f50b251 (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.h | 4 | ||||
-rw-r--r-- | src/gtkext/gtkbinview.c | 8 | ||||
-rw-r--r-- | src/gtkext/gtkblockview.c | 326 | ||||
-rw-r--r-- | src/gtkext/gtkgraphview.c | 80 |
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. * |