Branch: refs/heads/master Author: Dimitar Zhekov dimitar.zhekov@gmail.com Committer: Dimitar Zhekov dimitar.zhekov@gmail.com Date: Sat, 21 Sep 2013 17:46:16 UTC Commit: 848f75e48f10ee96f299ffdc5447577c7fa008ee https://github.com/geany/geany-plugins/commit/848f75e48f10ee96f299ffdc544757...
Log Message: ----------- scope - register ScpTreeStore dynamically, making Scope unloadable again
Modified Paths: -------------- scope/ChangeLog scope/NOTES scope/docs/scope.html scope/src/break.c scope/src/conterm.c scope/src/debug.c scope/src/inspect.c scope/src/memory.c scope/src/menu.c scope/src/parse.c scope/src/prefs.c scope/src/program.c scope/src/register.c scope/src/scope.c scope/src/stack.c scope/src/store/ChangeLog scope/src/store/fullspeed.html scope/src/store/scptreestore.c scope/src/store/scptreestore.h scope/src/store/scptreestore.html scope/src/thread.c scope/src/tooltip.c scope/src/tooltip.h scope/src/views.c
Modified: scope/ChangeLog 19 files changed, 17 insertions(+), 2 deletions(-) =================================================================== @@ -1,3 +1,18 @@ +2013-07-25 Dimitar Zhekov dimitar.zhekov@gmail.com + + * src/scope.c: + Register ScpTreeStore dynamically, making Scope unloadable again. + * src/break.c, src/conterm.c, src/debug.c, src/inspect.c, + src/memory.c, src/menu.c, src/parse.c, src/program.c, + src/register.c, src/scope.c, src/stack.c, src/thread.c, + src/tooltip.c, src/tooltip.h, src/views.c: + Reverted the startup variable initialization from 2013-07-25. + * src/conterm.c, src/inspect.c, src/prefs.c, src/watch.c: + Small startup changes. + * docs/scope.html, src/scope.c: + Increased version to 0.93. + + 2013-09-07 Dimitar Zhekov dimitar.zhekov@gmail.com
* data/scope.glade: @@ -55,8 +70,8 @@ src/memory.c, src/menu.c, src/parse.c, src/program.c, src/register.c, src/scope.c, src/stack.c, src/thread.c, src/tooltip.c, src/tooltip.h, src/views.c: - Explicitly initialize all sensitive global and static variables, - since reloading the plugin will not do that. + Explicitly initialize all sensitive global and static variables on + startup, since reactivating a resident plugin will not do that. * src/store/scptreestore.c: Fixed indentation. * docs/scope.html, src/scope.c:
Modified: scope/NOTES 3 files changed, 0 insertions(+), 3 deletions(-) =================================================================== @@ -1,9 +1,6 @@ -var-evaluate-expression reports the value from the last -var-update or -var-assign execution, not the current value
-reloading a resident geany plugin module does not reinitialize any global -and static variables, so the sensitive ones must be initialized explicitly - register modified is 07 since changing a register ($dh, $mm1.uint64) may change another ($dx, $st1), and there is some chance of watches/inspects containing a register
Modified: scope/docs/scope.html 2 files changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -748,7 +748,7 @@
<b><a name="copyright">Copyright</a></b>
-<p>Scope 0.92, Copyright (C) 2013 Dimitar Toshkov Zhekov</p> +<p>Scope 0.93, Copyright (C) 2013 Dimitar Toshkov Zhekov</p>
<p>The menu and toolbar icons are from <a href="http://netbeans.org">Netbeans</a>, except for BreakPoint.</p>
Modified: scope/src/break.c 4 files changed, 1 insertions(+), 3 deletions(-) =================================================================== @@ -676,7 +676,7 @@ void on_break_list(GArray *nodes) } }
-gint break_async; +gint break_async = -1;
void on_break_stopped(GArray *nodes) { @@ -1288,8 +1288,6 @@ void break_init(void) GtkWidget *menu; guint i;
- break_async = -1; - tree = view_connect("break_view", &store, &selection, break_cells, "break_window", NULL); gtk_tree_view_column_set_cell_data_func(get_column("break_type_column"), GTK_CELL_RENDERER(get_object("break_type")), break_type_set_data_func, NULL, NULL);
Modified: scope/src/conterm.c 33 files changed, 13 insertions(+), 20 deletions(-) =================================================================== @@ -28,7 +28,6 @@
#define NFD 5 #define DS_COPY (DS_BASICS | DS_EXTRA_1) -static int last_console_fd;
#ifdef G_OS_UNIX #if (defined(__unix__) || defined(unix)) && !defined(USG) @@ -166,22 +165,23 @@ void on_vte_realize(VteTerminal *vte, G_GNUC_UNUSED gpointer gdata) #endif }
-static VteTerminal *debug_console; /* NULL -> GtkTextView "context" */ +static VteTerminal *debug_console = NULL; /* NULL -> GtkTextView "context" */
static void console_output(int fd, const char *text, gint length) { static const char fd_colors[NFD] = { '6', '7', '1', '7', '5' }; static char setaf[5] = { '\033', '[', '3', '?', 'm' }; + static int last_fd = -1; gint i;
- if (last_console_fd == 3 && fd != 0) + if (last_fd == 3 && fd != 0) vte_terminal_feed(debug_console, "\r\n", 2);
- if (fd != last_console_fd) + if (fd != last_fd) { setaf[3] = fd_colors[fd]; vte_terminal_feed(debug_console, setaf, sizeof setaf); - last_console_fd = fd; + last_fd = fd; }
if (length == -1) @@ -214,20 +214,21 @@ static void console_output_nl(int fd, const char *text, gint length) static GtkTextTag *fd_tags[NFD]; #define DC_LIMIT 32768 /* approx */ #define DC_DELTA 6144 -static guint dc_chars; +static guint dc_chars = 0;
void context_output(int fd, const char *text, gint length) { + static int last_fd = -1; GtkTextIter end; gchar *utf8;
gtk_text_buffer_get_end_iter(context, &end);
- if (last_console_fd == 3 && fd != 0) + if (last_fd == 3 && fd != 0) gtk_text_buffer_insert(context, &end, "\n", 1);
- if (fd != last_console_fd) - last_console_fd = fd; + if (fd != last_fd) + last_fd = fd;
if (length == -1) length = strlen(text); @@ -421,8 +422,8 @@ void conterm_apply_config(void) }
#ifdef G_OS_UNIX -static int pty_slave; -char *slave_pty_name; +static int pty_slave = -1; +char *slave_pty_name = NULL; #endif
void conterm_init(void) @@ -434,11 +435,8 @@ void conterm_init(void) char *pty_name; #endif
- last_console_fd = -1; + conterm_load_config(); #ifdef G_OS_UNIX - pty_slave = -1; - slave_pty_name = NULL; - program_window = get_widget("program_window"); console = vte_terminal_new(); gtk_widget_show(console); @@ -535,11 +533,6 @@ void conterm_init(void) "#C0C0C0", "#C000C0" }; guint i;
- #ifdef G_OS_UNIX - debug_console = NULL; - #endif - dc_chars = 0; - console = get_widget("debug_context"); context_apply_config(console); debug_context = GTK_TEXT_VIEW(console);
Modified: scope/src/debug.c 7 files changed, 2 insertions(+), 5 deletions(-) =================================================================== @@ -78,7 +78,7 @@ static int kill(HANDLE pid, int sig) KILLING } GdbState;
-static GdbState gdb_state; +static GdbState gdb_state = INACTIVE; static GSource *gdb_source; static GPid gdb_pid;
@@ -266,7 +266,7 @@ static gboolean source_check(G_GNUC_UNUSED GSource *source) } #endif /* G_OS_UNIX */
-static guint source_id; +static guint source_id = 0;
static gboolean source_dispatch(G_GNUC_UNUSED GSource *source, G_GNUC_UNUSED GSourceFunc callback, G_GNUC_UNUSED gpointer gdata) @@ -748,9 +748,6 @@ char *debug_send_evaluate(char token, gint scid, const gchar *expr)
void debug_init(void) { - gdb_state = INACTIVE; - source_id = 0; - commands = g_string_sized_new(0x3FFF); received = g_string_sized_new(pref_gdb_buffer_length); MAXLEN = received->allocated_len - 1;
Modified: scope/src/inspect.c 20 files changed, 8 insertions(+), 12 deletions(-) =================================================================== @@ -163,7 +163,7 @@ static void on_jump_to_menu_item_activate(GtkMenuItem *menuitem, G_GNUC_UNUSED g
static GtkWidget *jump_to_item; static GtkContainer *jump_to_menu; -static gchar *jump_to_expr; +static gchar *jump_to_expr = NULL;
static void on_inspect_row_inserted(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, G_GNUC_UNUSED gpointer gdata) @@ -480,7 +480,7 @@ static void inspect_node_change(const ParseNode *node, G_GNUC_UNUSED gpointer gd } }
-static gboolean query_all_inspects; +static gboolean query_all_inspects = FALSE;
void on_inspect_changelist(GArray *nodes) { @@ -687,10 +687,10 @@ static void on_inspect_display_edited(G_GNUC_UNUSED GtkCellRendererText *rendere };
static GObject *inspect_display; -static gboolean last_state_active;
void inspects_update_state(DebugState state) { + static gboolean last_active = FALSE; gboolean active = state != DS_INACTIVE; GtkTreeIter iter;
@@ -707,11 +707,11 @@ void inspects_update_state(DebugState state) g_object_set(inspect_display, "editable", var1 && !numchild, NULL); }
- if (active != last_state_active) + if (active != last_active) { gtk_widget_set_sensitive(jump_to_item, active && scp_tree_store_get_iter_first(store, &iter)); - last_state_active = active; + last_active = active; } }
@@ -978,7 +978,7 @@ static void on_inspect_delete(G_GNUC_UNUSED const MenuItem *menu_item)
static MenuItem inspect_menu_items[] = { - { "inspect_refresh", on_inspect_refresh, DS_DEBUG, NULL, NULL }, + { "inspect_refresh", on_inspect_refresh, DS_VARIABLE, NULL, NULL }, { "inspect_add", on_inspect_add, DS_NOT_BUSY, NULL, NULL }, { "inspect_edit", on_inspect_edit, DS_EDITABLE, NULL, NULL }, { "inspect_apply", on_inspect_apply, DS_APPLIABLE, NULL, NULL }, @@ -1133,10 +1133,6 @@ void inspect_init(void) { GtkWidget *menu;
- jump_to_expr = NULL; - query_all_inspects = FALSE; - last_state_active = FALSE; - jump_to_item = get_widget("inspect_jump_to_item"); jump_to_menu = GTK_CONTAINER(get_widget("inspect_jump_to_menu")); apply_item = menu_item_find(inspect_menu_items, "inspect_apply"); @@ -1155,8 +1151,8 @@ void inspect_init(void) g_signal_connect(selection, "changed", G_CALLBACK(on_inspect_selection_changed), NULL); menu = menu_select("inspect_menu", &inspect_menu_info, selection); g_signal_connect(menu, "show", G_CALLBACK(on_inspect_menu_show), NULL); - if (!pref_var_update_bug) - inspect_menu_items->state = DS_VARIABLE; + if (pref_var_update_bug) + inspect_menu_items->state = DS_DEBUG;
inspect_dialog = dialog_connect("inspect_dialog"); inspect_name = GTK_ENTRY(get_widget("inspect_name_entry"));
Modified: scope/src/memory.c 7 files changed, 2 insertions(+), 5 deletions(-) =================================================================== @@ -117,7 +117,7 @@ static void on_memory_bytes_editing_started(G_GNUC_UNUSED GtkCellRenderer *cell,
static gint back_bytes_per_line; static gint bytes_per_line; -static gint bytes_per_group; +static gint bytes_per_group = 1;
static void memory_configure(void) { @@ -133,7 +133,7 @@ static void memory_configure(void) }
static guint64 memory_start; -static guint memory_count; +static guint memory_count = 0; #define MAX_BYTES (128 * MAX_BYTES_PER_LINE) /* +1 incomplete line */
static void write_block(guint64 start, const char *contents, guint count) @@ -382,9 +382,6 @@ void memory_init(void) GtkWidget *tree = GTK_WIDGET(view_connect("memory_view", &store, &selection, memory_cells, "memory_window", NULL));
- bytes_per_group = 1; - memory_count = 0; - memory_font = *pref_memory_font ? pref_memory_font : pref_vte_font; ui_widget_modify_font_from_string(tree, memory_font); g_signal_connect(get_object("memory_bytes"), "editing-started",
Modified: scope/src/menu.c 10 files changed, 3 insertions(+), 7 deletions(-) =================================================================== @@ -51,7 +51,7 @@ void menu_item_execute(const MenuInfo *menu_info, const MenuItem *menu_item, gbo plugin_beep(); }
-static gboolean block_execute; +static gboolean block_execute = FALSE;
void menu_item_set_active(const MenuItem *menu_item, gboolean active) { @@ -109,7 +109,7 @@ static void on_menu_item_activate(GtkMenuItem *menuitem, MenuInfo *menu_info) } }
-static MenuInfo *active_menu; +static MenuInfo *active_menu = NULL;
static void update_active_menu(guint state) { @@ -404,7 +404,7 @@ void on_menu_update_boolean(const MenuItem *menu_item) *(gboolean *) menu_item->gdata = gtk_check_menu_item_get_active(item); }
-static char *input; +static char *input = NULL; static gint eval_mr_mode; static gint scid_gen = 0;
@@ -519,10 +519,6 @@ void menu_init(void) GList *children = gtk_container_get_children(GTK_CONTAINER(shell)); GtkWidget *search2 = find_widget(shell, "search2");
- block_execute = FALSE; - active_menu = NULL; - input = NULL; - popup_item = get_widget("popup_item"); menu_connect("popup_menu", &popup_menu_info, NULL); g_signal_connect(get_widget("popup_evaluate"), "button-release-event",
Modified: scope/src/parse.c 7 files changed, 2 insertions(+), 5 deletions(-) =================================================================== @@ -439,8 +439,8 @@ gchar *parse_get_error(GArray *nodes)
#define MAXLEN 0x7FF static GString *errors; -static guint errors_id; -static guint error_count; +static guint errors_id = 0; +static guint error_count = 0;
static gboolean errors_show(G_GNUC_UNUSED gpointer gdata) { @@ -620,9 +620,6 @@ void parse_save(GKeyFile *config)
void parse_init(void) { - errors_id = 0; - error_count = 0; - errors = g_string_sized_new(MAXLEN); parse_modes = SCP_TREE_STORE(get_object("parse_mode_store")); scp_tree_store_set_sort_column_id(parse_modes, MODE_NAME, GTK_SORT_ASCENDING);
Modified: scope/src/prefs.c 2 files changed, 0 insertions(+), 2 deletions(-) =================================================================== @@ -309,8 +309,6 @@ void prefs_init(void) g_key_file_free(config); g_free(configfile); g_free(configdir); - - conterm_load_config(); }
void prefs_finalize(void)
Modified: scope/src/program.c 3 files changed, 1 insertions(+), 2 deletions(-) =================================================================== @@ -307,7 +307,7 @@ void program_context_changed(void)
#define build_check_execute() (build_get_execute(GEANY_BC_COMMAND) || \ build_get_execute(GEANY_BC_WORKING_DIR)) -static gboolean last_state_inactive; +static gboolean last_state_inactive = TRUE;
void program_update_state(DebugState state) { @@ -442,7 +442,6 @@ void program_init(void) extern gboolean thread_select_on_exited; extern gboolean thread_select_follow;
- last_state_inactive = TRUE; program_dialog = dialog_connect("program_dialog"); program_page_vbox = get_widget("program_page_vbox");
Modified: scope/src/register.c 7 files changed, 2 insertions(+), 5 deletions(-) =================================================================== @@ -70,7 +70,7 @@ static void register_node_update(const ParseNode *node, GString *commands[]) } }
-static gboolean query_all_registers; +static gboolean query_all_registers = TRUE;
static void registers_send_update(GArray *nodes, char token) { @@ -330,7 +330,7 @@ gboolean registers_update(void) return TRUE; }
-static char *last_gdb_executable; +static char *last_gdb_executable = NULL;
void registers_query_names(void) { @@ -526,9 +526,6 @@ static void on_register_selection_changed(G_GNUC_UNUSED GtkTreeSelection *select
void register_init(void) { - query_all_registers = TRUE; - last_gdb_executable = NULL; - tree = GTK_WIDGET(view_connect("register_view", &store, &selection, register_cells, "register_window", ®ister_display)); gtk_widget_set_has_tooltip(tree, TRUE);
Modified: scope/src/scope.c 47 files changed, 18 insertions(+), 29 deletions(-) =================================================================== @@ -32,7 +32,7 @@ PLUGIN_VERSION_CHECK(215)
PLUGIN_SET_TRANSLATABLE_INFO(LOCALEDIR, GETTEXT_PACKAGE, _("Scope Debugger"), - _("Relatively simple GDB front-end."), "0.92", + _("Relatively simple GDB front-end."), "0.93", "Dimitar Toshkov Zhekov dimitar.zhekov@gmail.com")
/* Keybinding(s) */ @@ -191,13 +191,12 @@ static void on_toolbar_reconfigured(GtkToolItem *tool_item, ToolItem *item) get_widget(item->icon[large])); }
-static DebugState last_toolbar_state; - static void toolbar_update_state(DebugState state) { + static DebugState last_state = 0; state |= debug_menu_extra_state();
- if (state != last_toolbar_state) + if (state != last_state) { ToolItem *item;
@@ -207,7 +206,7 @@ static void toolbar_update_state(DebugState state) menu_item_matches_state(debug_menu_items + item->index, state)); }
- last_toolbar_state = state; + last_state = state; } }
@@ -219,10 +218,12 @@ static void toolbar_update_state(DebugState state)
void statusbar_update_state(DebugState state) { + static DebugState last_state = DS_INACTIVE; + if (thread_state == THREAD_AT_ASSEMBLER) state = DS_EXTRA_1;
- if (state != last_statusbar_state) + if (state != last_state) { static const char *const states[] = { N_("Busy"), N_("Ready"), N_("Debug"), N_("Hang"), N_("Assem"), N_("Load"), NULL }; @@ -243,7 +244,7 @@ void statusbar_update_state(DebugState state) gtk_statusbar_set_has_resize_grip(geany_statusbar, TRUE); #endif } - else if (last_statusbar_state == DS_INACTIVE) + else if (last_state == DS_INACTIVE) { #if GTK_CHECK_VERSION(3, 0, 0) gtk_window_set_has_resize_grip(GTK_WINDOW(geany->main_widgets->window), FALSE); @@ -253,11 +254,11 @@ void statusbar_update_state(DebugState state) gtk_widget_show(debug_statusbar); }
- last_statusbar_state = state; + last_state = state; } }
-static guint blink_id; +static guint blink_id = 0;
static gboolean plugin_unblink(G_GNUC_UNUSED gpointer gdata) { @@ -313,9 +314,9 @@ static void on_document_open(G_GNUC_UNUSED GObject *obj, GeanyDocument *doc, threads_mark(doc); }
-static guint after_save_id; +static guint saved_id = 0;
-static gboolean settings_after_save(gpointer gdata) +static gboolean settings_saved(gpointer gdata) { guint i;
@@ -331,16 +332,15 @@ static gboolean settings_after_save(gpointer gdata) conterm_apply_config(); }
- after_save_id = 0; + saved_id = 0; return FALSE; }
-static void schedule_after_save(gboolean conterm) +static void schedule_settings_saved(gboolean conterm) { guint i;
- after_save_id = plugin_idle_add(geany_plugin, settings_after_save, - GINT_TO_POINTER(conterm)); + saved_id = plugin_idle_add(geany_plugin, settings_saved, GINT_TO_POINTER(conterm));
foreach_document(i) { @@ -353,13 +353,13 @@ static void on_settings_save(G_GNUC_UNUSED GObject *obj, G_GNUC_UNUSED GKeyFile G_GNUC_UNUSED gpointer gdata) { configure_panel(); - schedule_after_save(TRUE); + schedule_settings_saved(TRUE); }
static void on_project_before_save(G_GNUC_UNUSED GObject *obj, G_GNUC_UNUSED GKeyFile *keyfile, G_GNUC_UNUSED gpointer gdata) { - schedule_after_save(FALSE); + schedule_settings_saved(FALSE); }
static gboolean on_editor_notify(G_GNUC_UNUSED GObject *obj, GeanyEditor *editor, @@ -541,21 +541,11 @@ void plugin_init(G_GNUC_UNUSED GeanyData *gdata) ToolItem *tool_item = toolbar_items; const ScopeCallback *scb;
- last_toolbar_state = 0; - last_statusbar_state = DS_INACTIVE; - blink_id = 0; - after_save_id = 0; - main_locale_init(LOCALEDIR, GETTEXT_PACKAGE); scope_key_group = plugin_set_key_group(geany_plugin, "scope", COUNT_KB, NULL); builder = gtk_builder_new(); gtk_builder_set_translation_domain(builder, GETTEXT_PACKAGE); - - if (!g_type_from_name("ScpTreeStore")) - { - plugin_module_make_resident(geany_plugin); - scp_tree_store_get_type(); - } + scp_tree_store_register_dynamic();
if (!gtk_builder_add_from_file(builder, gladefile, &gerror)) { @@ -605,7 +595,6 @@ void plugin_init(G_GNUC_UNUSED GeanyData *gdata) conterm_init(); inspect_init(); register_init(); - tooltip_init(); parse_init(); debug_init(); views_init();
Modified: scope/src/stack.c 4 files changed, 1 insertions(+), 3 deletions(-) =================================================================== @@ -62,7 +62,7 @@ static void stack_node_location(const ParseNode *node, const char *fid) } }
-const char *frame_id; +const char *frame_id = NULL;
void on_stack_frames(GArray *nodes) { @@ -336,8 +336,6 @@ void stack_init(void) GtkTreeView *tree = view_create("stack_view", &store, &selection); GtkWidget *menu = menu_select("stack_menu", &stack_menu_info, selection);
- frame_id = NULL; - view_set_sort_func(store, STACK_ID, store_gint_compare); view_set_sort_func(store, STACK_FILE, store_seek_compare); view_set_line_data_func("stack_line_column", "stack_line", STACK_LINE);
Modified: scope/src/store/ChangeLog 14 files changed, 13 insertions(+), 1 deletions(-) =================================================================== @@ -1,9 +1,21 @@ +2013-09-20 Dimitar Zhekov dimitar.zhekov@gmail.com + + * scptreestore.c, scptreestore.h, scptreestore.html: + Added scp_tree_store_register_dynamic(). + * scptreestore.html, fullspeed.html: + Moved the full speed test results to a separate file. + Increased version to 0.85. + * speed.c: + Replaced // with /* */ for glib/gtk+ compliance. + 2013-05-16 Dimitar Zhekov dimitar.zhekov@gmail.com
* scptreestore.c, scptreestore.h: - Added scp_tree_store_traverse(). Moved scp_tree_store_iter_tell() from Extra to Store, it's required to insert before/after and move. + Added scp_tree_store_traverse(). * scptreestore.html: Documentation and speed test results for scp_tree_store_traverse(). Increased version to 0.84. + * speed.c: + Added speed test for scp_tree_store_traverse().
Modified: scope/src/store/fullspeed.html 271 files changed, 271 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,271 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> + +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +<title>ScpTreeStore full speed test</title> +<style type="text/css"> + .tab { padding-left:2em; } + table { border-collapse:collapse; } + th, td { border: 1px solid black; } + .empty { border: 0px; } + th, td { padding: 0em 0.5em; } +</style> +</head> + +<body> + +<h2>ScpTreeStore</h2> + +<h3>Full speed test</h3> + +<p>Notes:</p> + +<ul> +<li>pre/append = prepend for GtkTreeStore (faster than append), and append for<br> +ScpTreeStore (faster than prepend), though the speed difference is not significant</li> +<li>all defensive checks are enabled</li> +<li>all string tests are with utf8 collation</li> +<li>GtkListStore speed is almost identical to GtkTreeStore, and sometimes slower.</li> +</ul> + +<table> +<tr><th>Unsorted store</th><th>Row count</th><th>GtkTreeStore</th> +<th>ScpTreeStore</th><th>Times</th></tr> + +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>top-level insert</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>top-level set</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>top-level remove</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>top-level insert with values</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>top-level iter search double</td><td>25</td><td>0.000</td><td>0.000</td><td>25</td></tr> +<tr><td>top-level iter search string</td><td>25</td><td>0.003</td><td>0.002</td><td>25</td></tr> +<tr><td>top-level linear search double</td><td>25</td><td>n/a</td><td>0.000</td><td>25</td></tr> +<tr><td>top-level linear search string</td><td>25</td><td>n/a</td><td>0.001</td><td>25</td></tr> +<tr><td>both levels model foreach</td><td>25</td><td>0.000</td><td>0.000</td><td>25</td></tr> +<tr><td>both levels store traverse</td><td>25</td><td>n/a</td><td>0.000</td><td>25</td></tr> +<tr><td>top-level quick sort double</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>top-level quick sort string</td><td>25</td><td>0.001</td><td>0.000</td><td></td></tr> +<tr><td>sublevel 1 insert</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>sublevel 1 set</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>sublevel 1 remove</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>sublevel 1 insert_with values</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>sublevel 1 quick sort double</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>sublevel 1 quick sort string</td><td>25</td><td>0.001</td><td>0.001</td><td></td></tr> + +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>top-level insert</td><td>100</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>top-level set</td><td>100</td><td>0.001</td><td>0.000</td><td></td></tr> +<tr><td>top-level remove</td><td>100</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>top-level insert with values</td><td>100</td><td>0.001</td><td>0.000</td><td></td></tr> +<tr><td>top-level iter search double</td><td>100</td><td>0.006</td><td>0.000</td><td>100</td></tr> +<tr><td>top-level iter search string</td><td>100</td><td>0.034</td><td>0.027</td><td>100</td></tr> +<tr><td>top-level linear search double</td><td>100</td><td>n/a</td><td>0.000</td><td>100</td></tr> +<tr><td>top-level linear search string</td><td>100</td><td>n/a</td><td>0.015</td><td>100</td></tr> +<tr><td>both levels model foreach</td><td>100</td><td>0.003</td><td>0.003</td><td>100</td></tr> +<tr><td>both levels store traverse</td><td>100</td><td>n/a</td><td>0.000</td><td>100</td></tr> +<tr><td>top-level quick sort double</td><td>100</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>top-level quick sort string</td><td>100</td><td>0.003</td><td>0.002</td><td></td></tr> +<tr><td>sublevel 1 insert</td><td>100</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>sublevel 1 set</td><td>100</td><td>0.001</td><td>0.000</td><td></td></tr> +<tr><td>sublevel 1 remove</td><td>100</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>sublevel 1 insert with values</td><td>100</td><td>0.001</td><td>0.000</td><td></td></tr> +<tr><td>sublevel 1 quick sort double</td><td>100</td><td>0.001</td><td>0.000</td><td></td></tr> +<tr><td>sublevel 1 quick sort string</td><td>100</td><td>0.005</td><td>0.004</td><td></td></tr> + +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>top-level insert</td><td>250</td><td>0.001</td><td>0.001</td><td></td></tr> +<tr><td>top-level set</td><td>250</td><td>0.002</td><td>0.001</td><td></td></tr> +<tr><td>top-level remove</td><td>250</td><td>0.001</td><td>0.001</td><td></td></tr> +<tr><td>top-level insert with values</td><td>250</td><td>0.002</td><td>0.001</td><td></td></tr> +<tr><td>top-level iter search double</td><td>250</td><td>0.031</td><td>0.003</td><td>250</td></tr> +<tr><td>top-level iter search string</td><td>250</td><td>0.224</td><td>0.183</td><td>250</td></tr> +<tr><td>top-level linear search double</td><td>250</td><td>n/a</td><td>0.001</td><td>250</td></tr> +<tr><td>top-level linear search string</td><td>250</td><td>n/a</td><td>0.109</td><td>250</td></tr> +<tr><td>both levels model foreach</td><td>250</td><td>0.018</td><td>0.018</td><td>250</td></tr> +<tr><td>both levels store traverse</td><td>250</td><td>n/a</td><td>0.001</td><td>250</td></tr> +<tr><td>top-level quick sort double</td><td>250</td><td>0.001</td><td>0.000</td><td></td></tr> +<tr><td>top-level quick sort string</td><td>250</td><td>0.009</td><td>0.008</td><td></td></tr> +<tr><td>sublevel 1 insert</td><td>250</td><td>0.001</td><td>0.001</td><td></td></tr> +<tr><td>sublevel 1 set</td><td>250</td><td>0.002</td><td>0.001</td><td></td></tr> +<tr><td>sublevel 1 remove</td><td>250</td><td>0.001</td><td>0.001</td><td></td></tr> +<tr><td>sublevel 1 insert with values</td><td>250</td><td>0.002</td><td>0.001</td><td></td></tr> +<tr><td>sublevel 1 quick sort double</td><td>250</td><td>0.002</td><td>0.000</td><td></td></tr> +<tr><td>sublevel 1 quick sort string</td><td>250</td><td>0.015</td><td>0.012</td><td></td></tr> + +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>top-level insert</td><td>500</td><td>0.002</td><td>0.002</td><td></td></tr> +<tr><td>top-level set</td><td>500</td><td>0.003</td><td>0.002</td><td></td></tr> +<tr><td>top-level remove</td><td>500</td><td>0.002</td><td>0.001</td><td></td></tr> +<tr><td>top-level insert with values</td><td>500</td><td>0.003</td><td>0.002</td><td></td></tr> +<tr><td>top-level iter search double</td><td>500</td><td>0.131</td><td>0.010</td><td>500</td></tr> +<tr><td>top-level iter search string</td><td>500</td><td>0.909</td><td>0.722</td><td>500</td></tr> +<tr><td>top-level linear search double</td><td>500</td><td>n/a</td><td>0.005</td><td>500</td></tr> +<tr><td>top-level linear search string</td><td>500</td><td>n/a</td><td>0.443</td><td>500</td></tr> +<tr><td>both levels model foreach</td><td>500</td><td>0.077</td><td>0.076</td><td>500</td></tr> +<tr><td>both levels store traverse</td><td>500</td><td>n/a</td><td>0.003</td><td>500</td></tr> +<tr><td>top-level quick sort double</td><td>500</td><td>0.003</td><td>0.001</td><td></td></tr> +<tr><td>top-level quick sort string</td><td>500</td><td>0.022</td><td>0.018</td><td></td></tr> +<tr><td>sublevel 1 insert</td><td>500</td><td>0.002</td><td>0.002</td><td></td></tr> +<tr><td>sublevel 1 set</td><td>500</td><td>0.004</td><td>0.002</td><td></td></tr> +<tr><td>sublevel 1 remove</td><td>500</td><td>0.002</td><td>0.002</td><td></td></tr> +<tr><td>sublevel 1 insert with values</td><td>500</td><td>0.004</td><td>0.003</td><td></td></tr> +<tr><td>sublevel 1 quick sort double</td><td>500</td><td>0.005</td><td>0.001</td><td></td></tr> +<tr><td>sublevel 1 quick sort string</td><td>500</td><td>0.034</td><td>0.028</td><td></td></tr> + +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>top-level insert</td><td>1000</td><td>0.004</td><td>0.003</td><td></td></tr> +<tr><td>top-level set</td><td>1000</td><td>0.007</td><td>0.003</td><td></td></tr> +<tr><td>top-level remove</td><td>1000</td><td>0.004</td><td>0.003</td><td></td></tr> +<tr><td>top-level insert with values</td><td>1000</td><td>0.007</td><td>0.004</td><td></td></tr> +<tr><td>top-level iter search double</td><td>1000</td><td>0.052</td><td>0.004</td><td>100</td></tr> +<tr><td>top-level iter search string</td><td>1000</td><td>0.370</td><td>0.273</td><td>100</td></tr> +<tr><td>top-level linear search double</td><td>1000</td><td>n/a</td><td>0.002</td><td>100</td></tr> +<tr><td>top-level linear search string</td><td>1000</td><td>n/a</td><td>0.182</td><td>100</td></tr> +<tr><td>both levels model foreach</td><td>1000</td><td>0.033</td><td>0.030</td><td>100</td></tr> +<tr><td>both levels store traverse</td><td>1000</td><td>n/a</td><td>0.001</td><td>100</td></tr> +<tr><td>top-level quick sort double</td><td>1000</td><td>0.007</td><td>0.002</td><td></td></tr> +<tr><td>top-level quick sort string</td><td>1000</td><td>0.050</td><td>0.040</td><td></td></tr> +<tr><td>sublevel 1 insert</td><td>1000</td><td>0.006</td><td>0.004</td><td></td></tr> +<tr><td>sublevel 1 set</td><td>1000</td><td>0.009</td><td>0.005</td><td></td></tr> +<tr><td>sublevel 1 remove</td><td>1000</td><td>0.006</td><td>0.004</td><td></td></tr> +<tr><td>sublevel 1 insert with values</td><td>1000</td><td>0.009</td><td>0.006</td><td></td></tr> +<tr><td>sublevel 1 quick sort double</td><td>1000</td><td>0.011</td><td>0.002</td><td></td></tr> +<tr><td>sublevel 1 quick sort string</td><td>1000</td><td>0.078</td><td>0.062</td><td></td></tr> + +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>top-level insert</td><td>2500</td><td>0.017</td><td>0.008</td><td></td></tr> +<tr><td>top-level set</td><td>2500</td><td>0.026</td><td>0.009</td><td></td></tr> +<tr><td>top-level remove</td><td>2500</td><td>0.019</td><td>0.008</td><td></td></tr> +<tr><td>top-level insert with values</td><td>2500</td><td>0.026</td><td>0.012</td><td></td></tr> +<tr><td>top-level iter search double</td><td>2500</td><td>0.340</td><td>0.028</td><td>250</td></tr> +<tr><td>top-level iter search string</td><td>2500</td><td>2.273</td><td>1.859</td><td>250</td></tr> +<tr><td>top-level linear search double</td><td>2500</td><td>n/a</td><td>0.015</td><td>250</td></tr> +<tr><td>top-level linear search string</td><td>2500</td><td>n/a</td><td>1.137</td><td>250</td></tr> +<tr><td>both levels model foreach</td><td>2500</td><td>0.182</td><td>0.188</td><td>250</td></tr> +<tr><td>both levels store traverse</td><td>2500</td><td>n/a</td><td>0.009</td><td>250</td></tr> +<tr><td>top-level quick sort double</td><td>2500</td><td>0.021</td><td>0.004</td><td></td></tr> +<tr><td>top-level quick sort string</td><td>2500</td><td>0.146</td><td>0.117</td><td></td></tr> +<tr><td>sublevel 1 insert</td><td>2500</td><td>0.035</td><td>0.014</td><td></td></tr> +<tr><td>sublevel 1 set</td><td>2500</td><td>0.048</td><td>0.014</td><td></td></tr> +<tr><td>sublevel 1 remove</td><td>2500</td><td>0.038</td><td>0.013</td><td></td></tr> +<tr><td>sublevel 1 insert with values</td><td>2500</td><td>0.046</td><td>0.017</td><td></td></tr> +<tr><td>sublevel 1 quick sort double</td><td>2500</td><td>0.033</td><td>0.007</td><td></td></tr> +<tr><td>sublevel 1 quick sort string</td><td>2500</td><td>0.230</td><td>0.181</td><td></td></tr> + +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>top-level insert</td><td>5000</td><td>0.084</td><td>0.019</td><td></td></tr> +<tr><td>top-level set</td><td>5000</td><td>0.107</td><td>0.017</td><td></td></tr> +<tr><td>top-level remove</td><td>5000</td><td>0.089</td><td>0.018</td><td></td></tr> +<tr><td>top-level insert with values</td><td>5000</td><td>0.103</td><td>0.025</td><td></td></tr> +<tr><td>top-level iter search double</td><td>5000</td><td>1.271</td><td>0.112</td><td>500</td></tr> +<tr><td>top-level iter search string</td><td>5000</td><td>8.775</td><td>7.787</td><td>500</td></tr> +<tr><td>top-level linear search double</td><td>5000</td><td>n/a</td><td>0.060</td><td>500</td></tr> +<tr><td>top-level linear search string</td><td>5000</td><td>n/a</td><td>4.351</td><td>500</td></tr> +<tr><td>both levels model foreach</td><td>5000</td><td>0.741</td><td>0.754</td><td>500</td></tr> +<tr><td>both levels store traverse</td><td>5000</td><td>n/a</td><td>0.042</td><td>500</td></tr> +<tr><td>top-level quick sort double</td><td>5000</td><td>0.046</td><td>0.010</td><td></td></tr> +<tr><td>top-level quick sort string</td><td>5000</td><td>0.325</td><td>0.264</td><td></td></tr> +<tr><td>sublevel 1 insert</td><td>5000</td><td>0.168</td><td>0.040</td><td></td></tr> +<tr><td>sublevel 1 set</td><td>5000</td><td>0.201</td><td>0.038</td><td></td></tr> +<tr><td>sublevel 1 remove</td><td>5000</td><td>0.184</td><td>0.038</td><td></td></tr> +<tr><td>sublevel 1 insert with values</td><td>5000</td><td>0.199</td><td>0.046</td><td></td></tr> +<tr><td>sublevel 1 quick sort double</td><td>5000</td><td>0.073</td><td>0.015</td><td></td></tr> +<tr><td>sublevel 1 quick sort string</td><td>5000</td><td>0.508</td><td>0.405</td><td></td></tr> + +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>top-level insert</td><td>10000</td><td>0.410</td><td>0.049</td><td></td></tr> +<tr><td>top-level set</td><td>10000</td><td>0.465</td><td>0.035</td><td></td></tr> +<tr><td>top-level remove</td><td>10000</td><td>0.430</td><td>0.045</td><td></td></tr> +<tr><td>top-level insert with values</td><td>10000</td><td>0.461</td><td>0.059</td><td></td></tr> +<tr><td>top-level iter search double</td><td>10000</td><td>7.434</td><td>0.509</td><td>1000</td></tr> +<tr><td>top-level iter search string</td><td>10000</td><td>37.555</td><td>31.020</td><td>1000</td></tr> +<tr><td>top-level linear search double</td><td>10000</td><td>n/a</td><td>0.304</td><td>1000</td></tr> +<tr><td>top-level linear search string</td><td>10000</td><td>n/a</td><td>18.896</td><td>1000</td></tr> +<tr><td>both levels model foreach</td><td>10000</td><td>2.969</td><td>3.136</td><td>1000</td></tr> +<tr><td>both levels store traverse</td><td>10000</td><td>n/a</td><td>0.238</td><td>1000</td></tr> +<tr><td>top-level quick sort double</td><td>10000</td><td>0.112</td><td>0.022</td><td></td></tr> +<tr><td>top-level quick sort string</td><td>10000</td><td>0.720</td><td>0.580</td><td></td></tr> +<tr><td>sublevel 1 insert</td><td>10000</td><td>1.152</td><td>0.132</td><td></td></tr> +<tr><td>sublevel 1 set</td><td>10000</td><td>1.730</td><td>0.116</td><td></td></tr> +<tr><td>sublevel 1 remove</td><td>10000</td><td>1.364</td><td>0.128</td><td></td></tr> +<tr><td>sublevel 1 insert with values</td><td>10000</td><td>1.427</td><td>0.146</td><td></td></tr> +<tr><td>sublevel 1 quick sort double</td><td>10000</td><td>0.170</td><td>0.034</td><td></td></tr> +<tr><td>sublevel 1 quick sort string</td><td>10000</td><td>1.114</td><td>0.893</td><td></td></tr> + +<tr><td colspan="5" class="empty"> </td></tr> +<tr><th>Store sorted by double</th><th>Row count</th><th>GtkTreeStore</th> +<th>ScpTreeStore</th><th>Times</th></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>25</td><td>0.003</td><td>0.000</td><td></td></tr> +<tr><td>pre/append with values</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> +<tr><td>binary search</td><td>25</td><td>n/a</td><td>0.000</td><td>25</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>100</td><td>0.004</td><td>0.001</td><td></td></tr> +<tr><td>pre/append with values</td><td>100</td><td>0.003</td><td>0.000</td><td></td></tr> +<tr><td>binary search</td><td>100</td><td>n/a</td><td>0.000</td><td>100</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>250</td><td>0.019</td><td>0.003</td><td></td></tr> +<tr><td>pre/append with values</td><td>250</td><td>0.015</td><td>0.001</td><td></td></tr> +<tr><td>binary search</td><td>250</td><td>n/a</td><td>0.000</td><td>250</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>500</td><td>0.068</td><td>0.007</td><td></td></tr> +<tr><td>pre/append with values</td><td>500</td><td>0.054</td><td>0.003</td><td></td></tr> +<tr><td>binary search</td><td>500</td><td>n/a</td><td>0.000</td><td>500</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>1000</td><td>0.225</td><td>0.015</td><td></td></tr> +<tr><td>pre/append with values</td><td>1000</td><td>0.203</td><td>0.006</td><td></td></tr> +<tr><td>binary search</td><td>1000</td><td>n/a</td><td>0.001</td><td>1000</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>2500</td><td>1.474</td><td>0.044</td><td></td></tr> +<tr><td>pre/append with values</td><td>2500</td><td>1.324</td><td>0.015</td><td></td></tr> +<tr><td>binary search</td><td>2500</td><td>n/a</td><td>0.002</td><td>2500</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>5000</td><td>6.432</td><td>0.115</td><td></td></tr> +<tr><td>pre/append with values</td><td>5000</td><td>5.624</td><td>0.035</td><td></td></tr> +<tr><td>binary search</td><td>5000</td><td>n/a</td><td>0.004</td><td>5000</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>10000</td><td>26.967</td><td>0.335</td><td></td></tr> +<tr><td>pre/append with values</td><td>10000</td><td>23.803</td><td>0.081</td><td></td></tr> +<tr><td>binary search</td><td>10000</td><td>n/a</td><td>0.009</td><td>10000</td></tr> + +<tr><td colspan="5" class="empty"> </td></tr> +<tr><th>Store sorted by string</th><th>Row count</th><th>GtkTreeStore</th> +<th>ScpTreeStore</th><th>Times</th></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>25</td><td>0.003</td><td>0.001</td><td></td></tr> +<tr><td>pre/append with values</td><td>25</td><td>0.001</td><td>0.001</td><td></td></tr> +<tr><td>binary search</td><td>25</td><td>n/a</td><td>0.000</td><td>25</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>100</td><td>0.014</td><td>0.005</td><td></td></tr> +<tr><td>pre/append with values</td><td>100</td><td>0.014</td><td>0.003</td><td></td></tr> +<tr><td>binary search</td><td>100</td><td>n/a</td><td>0.002</td><td>100</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>250</td><td>0.092</td><td>0.015</td><td></td></tr> +<tr><td>pre/append with values</td><td>250</td><td>0.093</td><td>0.009</td><td></td></tr> +<tr><td>binary search</td><td>250</td><td>n/a</td><td>0.006</td><td>250</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>500</td><td>0.366</td><td>0.034</td><td></td></tr> +<tr><td>pre/append with values</td><td>500</td><td>0.343</td><td>0.021</td><td></td></tr> +<tr><td>binary search</td><td>500</td><td>n/a</td><td>0.012</td><td>500</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>1000</td><td>1.415</td><td>0.077</td><td></td></tr> +<tr><td>pre/append with values</td><td>1000</td><td>1.444</td><td>0.047</td><td></td></tr> +<tr><td>binary search</td><td>1000</td><td>n/a</td><td>0.028</td><td>1000</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>2500</td><td>9.032</td><td>0.229</td><td></td></tr> +<tr><td>pre/append with values</td><td>2500</td><td>9.061</td><td>0.134</td><td></td></tr> +<tr><td>binary search</td><td>2500</td><td>n/a</td><td>0.080</td><td>2500</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>5000</td><td>36.648</td><td>0.521</td><td></td></tr> +<tr><td>pre/append with values</td><td>5000</td><td>38.045</td><td>0.296</td><td></td></tr> +<tr><td>binary search</td><td>5000</td><td>n/a</td><td>0.177</td><td>5000</td></tr> +<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td>pre/apppend + set</td><td>10000</td><td>slow</td><td>1.225</td><td></td></tr> +<tr><td>pre/append with values</td><td>10000</td><td>slow</td><td>0.654</td><td></td></tr> +<tr><td>binary search</td><td>10000</td><td>n/a</td><td>0.385</td><td>10000</td></tr> + +</table> + +</body> +</html>
Modified: scope/src/store/scptreestore.c 168 files changed, 112 insertions(+), 56 deletions(-) =================================================================== @@ -147,16 +147,15 @@ ScpTreeStore *scp_tree_store_newv(gboolean sublevels, gint n_columns, GType *typ ScpTreeStore *store;
g_return_val_if_fail(n_columns > 0, NULL); - store = g_object_new(SCP_TYPE_TREE_STORE, NULL); + store = g_object_new(SCP_TYPE_TREE_STORE, "sublevels", sublevels != FALSE, NULL);
- if (scp_tree_store_set_column_types(store, n_columns, types)) + if (!scp_tree_store_set_column_types(store, n_columns, types)) { - store->priv->sublevels = sublevels; - return store; + g_object_unref(store); + store = NULL; }
- g_object_unref(store); - return NULL; + return store; }
#define scp_tree_model_compare_func ((GtkTreeIterCompareFunc) scp_tree_store_compare_func) @@ -1796,15 +1795,6 @@ static void scp_tree_store_buildable_init(GtkBuildableIface *iface) iface->custom_finished = scp_tree_store_buildable_custom_finished; }
-static void scp_tree_store_finalize(GObject *object); - -G_DEFINE_TYPE_WITH_CODE(ScpTreeStore, scp_tree_store, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL, scp_tree_store_tree_model_init) - G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_DRAG_SOURCE, scp_tree_store_drag_source_init) - G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_DRAG_DEST, scp_tree_store_drag_dest_init) - G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_SORTABLE, scp_tree_store_sortable_init) - G_IMPLEMENT_INTERFACE(GTK_TYPE_BUILDABLE, scp_tree_store_buildable_init)) - enum { PROP_0, @@ -1815,6 +1805,33 @@ enum PROP_UTF8_COLLATE };
+static gpointer scp_tree_store_parent_class = NULL; + +static GObject *scp_tree_store_constructor(GType type, guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GObject *object = G_OBJECT_CLASS(scp_tree_store_parent_class)->constructor(type, + n_construct_properties, construct_properties); + ScpTreeStorePrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE(object, SCP_TYPE_TREE_STORE, + ScpTreeStorePrivate); + + ((ScpTreeStore *) object)->priv = priv; + while ((priv->stamp = g_random_int()) == 0); /* we mark invalid iters with stamp 0 */ + priv->root = g_new0(AElem, 1); + priv->roar = g_ptr_array_new(); + scp_ptr_array_insert_val(priv->roar, 0, priv->root); + priv->headers = NULL; + priv->n_columns = 0; + priv->sort_column_id = GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID; + priv->sort_order = GTK_SORT_ASCENDING; + priv->sort_func = NULL; + priv->toplevel_reserved = 0; + priv->sublevel_reserved = 0; + priv->sublevel_discard = FALSE; + priv->columns_dirty = FALSE; + return object; +} + static void scp_tree_store_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { @@ -1855,6 +1872,8 @@ static void scp_tree_store_set_property(GObject *object, guint prop_id, const GV { case PROP_SUBLEVELS : { + priv = G_TYPE_INSTANCE_GET_PRIVATE(object, SCP_TYPE_TREE_STORE, + ScpTreeStorePrivate); /* ctor, store->priv is not assigned */ priv->sublevels = g_value_get_boolean(value); break; } @@ -1890,72 +1909,109 @@ static void scp_tree_store_set_property(GObject *object, guint prop_id, const GV #endif }
-static void scp_tree_store_class_init(ScpTreeStoreClass *class) +static void scp_tree_store_finalize(GObject *object) { - GObjectClass *object_class; + ScpTreeStore *store = SCP_TREE_STORE(object); + ScpTreeStorePrivate *priv = store->priv;
- object_class = (GObjectClass *) class; - object_class->finalize = scp_tree_store_finalize; - object_class->get_property = scp_tree_store_get_property; - object_class->set_property = scp_tree_store_set_property; + scp_free_array(store, priv->root->children); + g_free(priv->root); + g_ptr_array_free(priv->roar, TRUE); + + if (priv->headers) + scp_tree_data_headers_free(priv->n_columns, priv->headers); + + G_OBJECT_CLASS(scp_tree_store_parent_class)->finalize(object); +} + +static void scp_tree_store_gobject_init(GObjectClass *class) +{ + scp_tree_store_parent_class = g_type_class_peek_parent(class); + class->constructor = scp_tree_store_constructor; + class->finalize = scp_tree_store_finalize; + class->get_property = scp_tree_store_get_property; + class->set_property = scp_tree_store_set_property; +} + +static void scp_tree_store_class_init(GObjectClass *class) +{ + scp_tree_store_gobject_init(class); g_type_class_add_private(class, sizeof(ScpTreeStorePrivate)); - g_assert(GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID == -1); + g_assert(GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID == -1); /* headers[-1] = default */
- g_object_class_install_property(object_class, PROP_SUBLEVELS, + g_object_class_install_property(class, PROP_SUBLEVELS, g_param_spec_boolean("sublevels", P_("Sublevels"), P_("Supports sublevels (as opposed to flat list)"), TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
- g_object_class_install_property(object_class, PROP_TOPLEVEL_RESERVED, + g_object_class_install_property(class, PROP_TOPLEVEL_RESERVED, g_param_spec_uint("toplevel-reserved", P_("Toplevel reserved"), P_("Number of pointers preallocated for top-level elements"), 0, G_MAXINT32, 0, G_PARAM_READWRITE));
- g_object_class_install_property(object_class, PROP_SUBLEVEL_RESERVED, + g_object_class_install_property(class, PROP_SUBLEVEL_RESERVED, g_param_spec_uint("sublevel-reserved", P_("Sublevel reserved"), P_("Number of pointers preallocated for sublevel elements"), 0, G_MAXINT32, 0, G_PARAM_READWRITE));
- g_object_class_install_property(object_class, PROP_SUBLEVEL_DISCARD, + g_object_class_install_property(class, PROP_SUBLEVEL_DISCARD, g_param_spec_boolean("sublevel-discard", P_("Sublevel discard"), P_("Free sublevel arrays when their last element is removed"), FALSE, G_PARAM_READWRITE)); }
-static void scp_tree_store_init(ScpTreeStore *store) +static volatile gsize scp_tree_store_type_id_volatile = 0; + +GType scp_tree_store_get_type(void) { - ScpTreeStorePrivate *priv; + if (g_once_init_enter(&scp_tree_store_type_id_volatile)) + { + GType type = g_type_register_static_simple(G_TYPE_OBJECT, + g_intern_string("ScpTreeStore"), sizeof(ScpTreeStoreClass), + (GClassInitFunc) scp_tree_store_class_init, sizeof(ScpTreeStore), NULL, 0); + GInterfaceInfo iface_info = { (GInterfaceInitFunc) scp_tree_store_tree_model_init, + NULL, NULL }; + + g_type_add_interface_static(type, GTK_TYPE_TREE_MODEL, &iface_info); + iface_info.interface_init = (GInterfaceInitFunc) scp_tree_store_drag_source_init; + g_type_add_interface_static(type, GTK_TYPE_TREE_DRAG_SOURCE, &iface_info); + iface_info.interface_init = (GInterfaceInitFunc) scp_tree_store_drag_dest_init; + g_type_add_interface_static(type, GTK_TYPE_TREE_DRAG_DEST, &iface_info); + iface_info.interface_init = (GInterfaceInitFunc) scp_tree_store_sortable_init; + g_type_add_interface_static(type, GTK_TYPE_TREE_SORTABLE, &iface_info); + iface_info.interface_init = (GInterfaceInitFunc) scp_tree_store_buildable_init; + g_type_add_interface_static(type, GTK_TYPE_BUILDABLE, &iface_info); + g_once_init_leave(&scp_tree_store_type_id_volatile, type); + }
- priv = G_TYPE_INSTANCE_GET_PRIVATE(store, SCP_TYPE_TREE_STORE, ScpTreeStorePrivate); - store->priv = priv; - while ((priv->stamp = g_random_int()) == 0); /* we mark invalid iters with stamp 0 */ - priv->root = g_new0(AElem, 1); - priv->roar = g_ptr_array_new(); - scp_ptr_array_insert_val(priv->roar, 0, priv->root); - priv->headers = NULL; - priv->n_columns = 0; - priv->sort_column_id = GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID; - priv->sort_order = GTK_SORT_ASCENDING; - priv->sort_func = NULL; - priv->sublevels = TRUE; - priv->toplevel_reserved = 0; - priv->sublevel_reserved = 0; - priv->sublevel_discard = FALSE; - priv->columns_dirty = FALSE; + return scp_tree_store_type_id_volatile; }
-static void scp_tree_store_finalize(GObject *object) +void scp_tree_store_register_dynamic(void) { - ScpTreeStore *store = SCP_TREE_STORE(object); - ScpTreeStorePrivate *priv = store->priv; - - scp_free_array(store, priv->root->children); - g_free(priv->root); - g_ptr_array_free(priv->roar, TRUE); + GType type = g_type_from_name("ScpTreeStore");
- if (priv->headers) - scp_tree_data_headers_free(priv->n_columns, priv->headers); - - /* must chain up */ - G_OBJECT_CLASS(scp_tree_store_parent_class)->finalize(object); + if (!type) + { + type = scp_tree_store_get_type(); + g_type_class_unref(g_type_class_ref(type)); /* force class create */ + } + else if (!scp_tree_store_type_id_volatile) + { + /* external registration, repair */ + gpointer class = g_type_class_peek(type); + gpointer iface = g_type_interface_peek(class, GTK_TYPE_TREE_MODEL); + + scp_tree_store_gobject_init((GObjectClass *) class); + scp_tree_store_tree_model_init((GtkTreeModelIface *) iface); + iface = g_type_interface_peek(class, GTK_TYPE_TREE_DRAG_SOURCE); + scp_tree_store_drag_source_init((GtkTreeDragSourceIface *) iface); + iface = g_type_interface_peek(class, GTK_TYPE_TREE_DRAG_DEST); + scp_tree_store_drag_dest_init((GtkTreeDragDestIface *) iface); + iface = g_type_interface_peek(class, GTK_TYPE_TREE_SORTABLE); + scp_tree_store_sortable_init((GtkTreeSortableIface *) iface); + iface = g_type_interface_peek(class, GTK_TYPE_BUILDABLE); + scp_tree_store_buildable_init((GtkBuildableIface *) iface); + scp_tree_store_type_id_volatile = type; + } }
Modified: scope/src/store/scptreestore.h 1 files changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -156,6 +156,7 @@ typedef gint (*ScpTreeStoreTraverseFunc)(ScpTreeStore *store, GtkTreeIter *iter, gpointer gdata); gboolean scp_tree_store_traverse(ScpTreeStore *store, gboolean sublevels, GtkTreeIter *iter, GtkTreeIter *parent, ScpTreeStoreTraverseFunc func, gpointer gdata); +void scp_tree_store_register_dynamic(void);
G_END_DECLS
Modified: scope/src/store/scptreestore.html 300 files changed, 57 insertions(+), 243 deletions(-) =================================================================== @@ -4,9 +4,13 @@ <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>ScpTreeStore</title> - <style type="text/css"> +<style type="text/css"> .tab { padding-left:2em; } - </style> + table { border-collapse:collapse; } + th, td { border: 1px solid black; } + .empty { border: 0px; } + th, td { padding: 0em 0.5em; } +</style> </head>
<body> @@ -60,7 +64,8 @@ ScpTreeStore *<a href="#scp_tree_store_newv">scp_tree_store_newv</a>(gboolean sublevels, gint n_columns, GType *types);<br> gboolean scp_tree_store_set_column_types(ScpTreeStore *store, gint n_columns, GType *types);<br> -#define scp_tree_store_set_utf8_collate(store, utf8_collate) +void <a href="#scp_tree_store_set_utf8_collate">scp_tree_store_set_utf8_collate</a>(ScpTreeStore +*store, gint column, gboolean collate);<br> void scp_tree_store_set_valuesv(ScpTreeStore *store, GtkTreeIter *iter, gint *columns, GValue *values, gint n_values);<br> void scp_tree_store_set_value(ScpTreeStore *store, GtkTreeIter *iter, gint column, GValue @@ -287,14 +292,15 @@ collate);</b></p>
<div>Normally, all stores compare strings with g_utf8_collate(), which is linguistically -correct, but awfully slow. With the gtk+ stores, you can create a separate column with the -string keys if needed, and write a small compare function that does g_strcmp0(). The side -effects are that when a store is sorted by a non-standard function, setting the value of any -column causes a check if the row is properly sorted, and ScpTreeStore's binary search can not -be used.</div> -<div class="tab">collate = <tt>TRUE</tt>: use g_utf8_collate() to compare strings, should only -be used with string columns<br> -collate = <tt>FALSE</tt>: use g_strcmp0() to compare strings, no side effects.</div> +correct, but very slow. You can create a separate column with the string keys, of course, and +write a small compare function that does g_strcmp0(), but the side effects are that in a store +is sorted by a non-standard function, setting the value of any column causes a check if the +row is properly sorted, and ScpTreeStore's binary search can not be used.</div> +<div class="tab">collate = <tt>TRUE</tt>: use g_utf8_collate() to compare strings, only for +string columns<br> +collate = <tt>FALSE</tt>: use g_strcmp0() to compare strings, the above side effects mentioned +above. +</div>
<hr>
@@ -336,6 +342,8 @@ compare function is ignored, because it requires an iterator, not a value. For string columns, utf8_collate is taken into account.</p>
+<hr> + <h3><a name="ScpTreeStoreTraverseFunc">ScpTreeStoreTraverseFunc()</a></h3>
<p><b>gint ScpTreeStoreTraverseFunc(ScpTreeStore *store, GtkTreeIter *iter, gpointer gdata); @@ -362,9 +370,25 @@
<hr>
+<h3><a name="scp_tree_store_register_dynamic">scp_tree_store_register_dynamic()</a></h3> + +<p><b>scp_tree_store_register_dynamic(void);</b></p> + +<p>ScpTreeStore is written in a way that allows unloading the module which defines it, +provided that:</p> + +<ul> +<li>there are no stores in use</li> +<li>no attempts to create a store while the module is unloaded</li> +<li>this function is invoked once each time the module is (re)loaded, for example in it's +startup code.</li> +</ul> + +<hr> + <h3><a name="properties">Properties</a></h3>
-<p>"sublevels" (gboolean, read/construct only write) - whether the store supports +<p>"sublevels" (gboolean, read/construct) - whether the store supports sublevels.</p>
<p>"toplevel-reserved" (gint, read/write) - number of pointers to preallocate for @@ -412,264 +436,54 @@ reordered?]</p>
<p>When the top-level rows are being reordered, such iter may not be valid, because it must -point above the top. Both GtkTreeStore and ScpTreeStore pass a pseudo-valid iter which is -suitable for a few operations, but you should not rely on that and check for path depth = -<tt>0</tt> instead.</p> +point above the top. GtkTreeStore pass a pseudo-valid iter which is suitable for a few +operations, and so does ScpTreeStore, but you should not rely on that and check for path +depth = <tt>0</tt> instead.</p>
<hr>
<h3><a name="speed">Speed</a></h3>
-<table> -<tr><th>Unsorted store</th><th>Row count</th><th>GtkTreeStore</th> -<th>ScpTreeStore</th><th>Times</th></tr> - -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>top-level insert</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>top-level set</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>top-level remove</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>top-level insert with values</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>top-level iter search double</td><td>25</td><td>0.000</td><td>0.000</td><td>25</td></tr> -<tr><td>top-level iter search string</td><td>25</td><td>0.003</td><td>0.002</td><td>25</td></tr> -<tr><td>top-level linear search double</td><td>25</td><td>n/a</td><td>0.000</td><td>25</td></tr> -<tr><td>top-level linear search string</td><td>25</td><td>n/a</td><td>0.001</td><td>25</td></tr> -<tr><td>both levels model foreach</td><td>25</td><td>0.000</td><td>0.000</td><td>25</td></tr> -<tr><td>both levels store traverse</td><td>25</td><td>n/a</td><td>0.000</td><td>25</td></tr> -<tr><td>top-level quick sort double</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>top-level quick sort string</td><td>25</td><td>0.001</td><td>0.000</td><td></td></tr> -<tr><td>sublevel 1 insert</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>sublevel 1 set</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>sublevel 1 remove</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>sublevel 1 insert_with values</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>sublevel 1 quick sort double</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>sublevel 1 quick sort string</td><td>25</td><td>0.001</td><td>0.001</td><td></td></tr> - -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>top-level insert</td><td>100</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>top-level set</td><td>100</td><td>0.001</td><td>0.000</td><td></td></tr> -<tr><td>top-level remove</td><td>100</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>top-level insert with values</td><td>100</td><td>0.001</td><td>0.000</td><td></td></tr> -<tr><td>top-level iter search double</td><td>100</td><td>0.006</td><td>0.000</td><td>100</td></tr> -<tr><td>top-level iter search string</td><td>100</td><td>0.034</td><td>0.027</td><td>100</td></tr> -<tr><td>top-level linear search double</td><td>100</td><td>n/a</td><td>0.000</td><td>100</td></tr> -<tr><td>top-level linear search string</td><td>100</td><td>n/a</td><td>0.015</td><td>100</td></tr> -<tr><td>both levels model foreach</td><td>100</td><td>0.003</td><td>0.003</td><td>100</td></tr> -<tr><td>both levels store traverse</td><td>100</td><td>n/a</td><td>0.000</td><td>100</td></tr> -<tr><td>top-level quick sort double</td><td>100</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>top-level quick sort string</td><td>100</td><td>0.003</td><td>0.002</td><td></td></tr> -<tr><td>sublevel 1 insert</td><td>100</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>sublevel 1 set</td><td>100</td><td>0.001</td><td>0.000</td><td></td></tr> -<tr><td>sublevel 1 remove</td><td>100</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>sublevel 1 insert with values</td><td>100</td><td>0.001</td><td>0.000</td><td></td></tr> -<tr><td>sublevel 1 quick sort double</td><td>100</td><td>0.001</td><td>0.000</td><td></td></tr> -<tr><td>sublevel 1 quick sort string</td><td>100</td><td>0.005</td><td>0.004</td><td></td></tr> - -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>top-level insert</td><td>250</td><td>0.001</td><td>0.001</td><td></td></tr> -<tr><td>top-level set</td><td>250</td><td>0.002</td><td>0.001</td><td></td></tr> -<tr><td>top-level remove</td><td>250</td><td>0.001</td><td>0.001</td><td></td></tr> -<tr><td>top-level insert with values</td><td>250</td><td>0.002</td><td>0.001</td><td></td></tr> -<tr><td>top-level iter search double</td><td>250</td><td>0.031</td><td>0.003</td><td>250</td></tr> -<tr><td>top-level iter search string</td><td>250</td><td>0.224</td><td>0.183</td><td>250</td></tr> -<tr><td>top-level linear search double</td><td>250</td><td>n/a</td><td>0.001</td><td>250</td></tr> -<tr><td>top-level linear search string</td><td>250</td><td>n/a</td><td>0.109</td><td>250</td></tr> -<tr><td>both levels model foreach</td><td>250</td><td>0.018</td><td>0.018</td><td>250</td></tr> -<tr><td>both levels store traverse</td><td>250</td><td>n/a</td><td>0.001</td><td>250</td></tr> -<tr><td>top-level quick sort double</td><td>250</td><td>0.001</td><td>0.000</td><td></td></tr> -<tr><td>top-level quick sort string</td><td>250</td><td>0.009</td><td>0.008</td><td></td></tr> -<tr><td>sublevel 1 insert</td><td>250</td><td>0.001</td><td>0.001</td><td></td></tr> -<tr><td>sublevel 1 set</td><td>250</td><td>0.002</td><td>0.001</td><td></td></tr> -<tr><td>sublevel 1 remove</td><td>250</td><td>0.001</td><td>0.001</td><td></td></tr> -<tr><td>sublevel 1 insert with values</td><td>250</td><td>0.002</td><td>0.001</td><td></td></tr> -<tr><td>sublevel 1 quick sort double</td><td>250</td><td>0.002</td><td>0.000</td><td></td></tr> -<tr><td>sublevel 1 quick sort string</td><td>250</td><td>0.015</td><td>0.012</td><td></td></tr> - -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>top-level insert</td><td>500</td><td>0.002</td><td>0.002</td><td></td></tr> -<tr><td>top-level set</td><td>500</td><td>0.003</td><td>0.002</td><td></td></tr> -<tr><td>top-level remove</td><td>500</td><td>0.002</td><td>0.001</td><td></td></tr> -<tr><td>top-level insert with values</td><td>500</td><td>0.003</td><td>0.002</td><td></td></tr> -<tr><td>top-level iter search double</td><td>500</td><td>0.131</td><td>0.010</td><td>500</td></tr> -<tr><td>top-level iter search string</td><td>500</td><td>0.909</td><td>0.722</td><td>500</td></tr> -<tr><td>top-level linear search double</td><td>500</td><td>n/a</td><td>0.005</td><td>500</td></tr> -<tr><td>top-level linear search string</td><td>500</td><td>n/a</td><td>0.443</td><td>500</td></tr> -<tr><td>both levels model foreach</td><td>500</td><td>0.077</td><td>0.076</td><td>500</td></tr> -<tr><td>both levels store traverse</td><td>500</td><td>n/a</td><td>0.003</td><td>500</td></tr> -<tr><td>top-level quick sort double</td><td>500</td><td>0.003</td><td>0.001</td><td></td></tr> -<tr><td>top-level quick sort string</td><td>500</td><td>0.022</td><td>0.018</td><td></td></tr> -<tr><td>sublevel 1 insert</td><td>500</td><td>0.002</td><td>0.002</td><td></td></tr> -<tr><td>sublevel 1 set</td><td>500</td><td>0.004</td><td>0.002</td><td></td></tr> -<tr><td>sublevel 1 remove</td><td>500</td><td>0.002</td><td>0.002</td><td></td></tr> -<tr><td>sublevel 1 insert with values</td><td>500</td><td>0.004</td><td>0.003</td><td></td></tr> -<tr><td>sublevel 1 quick sort double</td><td>500</td><td>0.005</td><td>0.001</td><td></td></tr> -<tr><td>sublevel 1 quick sort string</td><td>500</td><td>0.034</td><td>0.028</td><td></td></tr> - -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>top-level insert</td><td>1000</td><td>0.004</td><td>0.003</td><td></td></tr> -<tr><td>top-level set</td><td>1000</td><td>0.007</td><td>0.003</td><td></td></tr> -<tr><td>top-level remove</td><td>1000</td><td>0.004</td><td>0.003</td><td></td></tr> -<tr><td>top-level insert with values</td><td>1000</td><td>0.007</td><td>0.004</td><td></td></tr> -<tr><td>top-level iter search double</td><td>1000</td><td>0.052</td><td>0.004</td><td>100</td></tr> -<tr><td>top-level iter search string</td><td>1000</td><td>0.370</td><td>0.273</td><td>100</td></tr> -<tr><td>top-level linear search double</td><td>1000</td><td>n/a</td><td>0.002</td><td>100</td></tr> -<tr><td>top-level linear search string</td><td>1000</td><td>n/a</td><td>0.182</td><td>100</td></tr> -<tr><td>both levels model foreach</td><td>1000</td><td>0.033</td><td>0.030</td><td>100</td></tr> -<tr><td>both levels store traverse</td><td>1000</td><td>n/a</td><td>0.001</td><td>100</td></tr> -<tr><td>top-level quick sort double</td><td>1000</td><td>0.007</td><td>0.002</td><td></td></tr> -<tr><td>top-level quick sort string</td><td>1000</td><td>0.050</td><td>0.040</td><td></td></tr> -<tr><td>sublevel 1 insert</td><td>1000</td><td>0.006</td><td>0.004</td><td></td></tr> -<tr><td>sublevel 1 set</td><td>1000</td><td>0.009</td><td>0.005</td><td></td></tr> -<tr><td>sublevel 1 remove</td><td>1000</td><td>0.006</td><td>0.004</td><td></td></tr> -<tr><td>sublevel 1 insert with values</td><td>1000</td><td>0.009</td><td>0.006</td><td></td></tr> -<tr><td>sublevel 1 quick sort double</td><td>1000</td><td>0.011</td><td>0.002</td><td></td></tr> -<tr><td>sublevel 1 quick sort string</td><td>1000</td><td>0.078</td><td>0.062</td><td></td></tr> - -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>top-level insert</td><td>2500</td><td>0.017</td><td>0.008</td><td></td></tr> -<tr><td>top-level set</td><td>2500</td><td>0.026</td><td>0.009</td><td></td></tr> -<tr><td>top-level remove</td><td>2500</td><td>0.019</td><td>0.008</td><td></td></tr> -<tr><td>top-level insert with values</td><td>2500</td><td>0.026</td><td>0.012</td><td></td></tr> -<tr><td>top-level iter search double</td><td>2500</td><td>0.340</td><td>0.028</td><td>250</td></tr> -<tr><td>top-level iter search string</td><td>2500</td><td>2.273</td><td>1.859</td><td>250</td></tr> -<tr><td>top-level linear search double</td><td>2500</td><td>n/a</td><td>0.015</td><td>250</td></tr> -<tr><td>top-level linear search string</td><td>2500</td><td>n/a</td><td>1.137</td><td>250</td></tr> -<tr><td>both levels model foreach</td><td>2500</td><td>0.182</td><td>0.188</td><td>250</td></tr> -<tr><td>both levels store traverse</td><td>2500</td><td>n/a</td><td>0.009</td><td>250</td></tr> -<tr><td>top-level quick sort double</td><td>2500</td><td>0.021</td><td>0.004</td><td></td></tr> -<tr><td>top-level quick sort string</td><td>2500</td><td>0.146</td><td>0.117</td><td></td></tr> -<tr><td>sublevel 1 insert</td><td>2500</td><td>0.035</td><td>0.014</td><td></td></tr> -<tr><td>sublevel 1 set</td><td>2500</td><td>0.048</td><td>0.014</td><td></td></tr> -<tr><td>sublevel 1 remove</td><td>2500</td><td>0.038</td><td>0.013</td><td></td></tr> -<tr><td>sublevel 1 insert with values</td><td>2500</td><td>0.046</td><td>0.017</td><td></td></tr> -<tr><td>sublevel 1 quick sort double</td><td>2500</td><td>0.033</td><td>0.007</td><td></td></tr> -<tr><td>sublevel 1 quick sort string</td><td>2500</td><td>0.230</td><td>0.181</td><td></td></tr> - -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>top-level insert</td><td>5000</td><td>0.084</td><td>0.019</td><td></td></tr> -<tr><td>top-level set</td><td>5000</td><td>0.107</td><td>0.017</td><td></td></tr> -<tr><td>top-level remove</td><td>5000</td><td>0.089</td><td>0.018</td><td></td></tr> -<tr><td>top-level insert with values</td><td>5000</td><td>0.103</td><td>0.025</td><td></td></tr> -<tr><td>top-level iter search double</td><td>5000</td><td>1.271</td><td>0.112</td><td>500</td></tr> -<tr><td>top-level iter search string</td><td>5000</td><td>8.775</td><td>7.787</td><td>500</td></tr> -<tr><td>top-level linear search double</td><td>5000</td><td>n/a</td><td>0.060</td><td>500</td></tr> -<tr><td>top-level linear search string</td><td>5000</td><td>n/a</td><td>4.351</td><td>500</td></tr> -<tr><td>both levels model foreach</td><td>5000</td><td>0.741</td><td>0.754</td><td>500</td></tr> -<tr><td>both levels store traverse</td><td>5000</td><td>n/a</td><td>0.042</td><td>500</td></tr> -<tr><td>top-level quick sort double</td><td>5000</td><td>0.046</td><td>0.010</td><td></td></tr> -<tr><td>top-level quick sort string</td><td>5000</td><td>0.325</td><td>0.264</td><td></td></tr> -<tr><td>sublevel 1 insert</td><td>5000</td><td>0.168</td><td>0.040</td><td></td></tr> -<tr><td>sublevel 1 set</td><td>5000</td><td>0.201</td><td>0.038</td><td></td></tr> -<tr><td>sublevel 1 remove</td><td>5000</td><td>0.184</td><td>0.038</td><td></td></tr> -<tr><td>sublevel 1 insert with values</td><td>5000</td><td>0.199</td><td>0.046</td><td></td></tr> -<tr><td>sublevel 1 quick sort double</td><td>5000</td><td>0.073</td><td>0.015</td><td></td></tr> -<tr><td>sublevel 1 quick sort string</td><td>5000</td><td>0.508</td><td>0.405</td><td></td></tr> +<p>An unsorted ScpTreeStore is faster than GtkTreeStore, but the difference is not big (20% +on average, depending on the operation and number of elements), and not significant (< 0.5+ +seconds) for stores with less than 10000 elements. Normally, inserting into and removing from +a list is faster than array, but all store operations must emit a signal, containing the row +path (numeric index), which negates this advantage.</p>
-<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>top-level insert</td><td>10000</td><td>0.410</td><td>0.049</td><td></td></tr> -<tr><td>top-level set</td><td>10000</td><td>0.465</td><td>0.035</td><td></td></tr> -<tr><td>top-level remove</td><td>10000</td><td>0.430</td><td>0.045</td><td></td></tr> -<tr><td>top-level insert with values</td><td>10000</td><td>0.461</td><td>0.059</td><td></td></tr> -<tr><td>top-level iter search double</td><td>10000</td><td>7.434</td><td>0.509</td><td>1000</td></tr> -<tr><td>top-level iter search string</td><td>10000</td><td>37.555</td><td>31.020</td><td>1000</td></tr> -<tr><td>top-level linear search double</td><td>10000</td><td>n/a</td><td>0.304</td><td>1000</td></tr> -<tr><td>top-level linear search string</td><td>10000</td><td>n/a</td><td>18.896</td><td>1000</td></tr> -<tr><td>both levels model foreach</td><td>10000</td><td>2.969</td><td>3.136</td><td>1000</td></tr> -<tr><td>both levels store traverse</td><td>10000</td><td>n/a</td><td>0.238</td><td>1000</td></tr> -<tr><td>top-level quick sort double</td><td>10000</td><td>0.112</td><td>0.022</td><td></td></tr> -<tr><td>top-level quick sort string</td><td>10000</td><td>0.720</td><td>0.580</td><td></td></tr> -<tr><td>sublevel 1 insert</td><td>10000</td><td>1.152</td><td>0.132</td><td></td></tr> -<tr><td>sublevel 1 set</td><td>10000</td><td>1.730</td><td>0.116</td><td></td></tr> -<tr><td>sublevel 1 remove</td><td>10000</td><td>1.364</td><td>0.128</td><td></td></tr> -<tr><td>sublevel 1 insert with values</td><td>10000</td><td>1.427</td><td>0.146</td><td></td></tr> -<tr><td>sublevel 1 quick sort double</td><td>10000</td><td>0.170</td><td>0.034</td><td></td></tr> -<tr><td>sublevel 1 quick sort string</td><td>10000</td><td>1.114</td><td>0.893</td><td></td></tr> +<p>The sorted gtk+ stores are slow, since they are based on lists, and sorting by a string +with utf8 collation makes them even slower.</p>
-<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<table> <tr><th>Store sorted by double</th><th>Row count</th><th>GtkTreeStore</th> <th>ScpTreeStore</th><th>Times</th></tr> <tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>pre/apppend + set</td><td>25</td><td>0.003</td><td>0.000</td><td></td></tr> -<tr><td>pre/append with values</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr> -<tr><td>binary search</td><td>25</td><td>n/a</td><td>0.000</td><td>25</td></tr> -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>pre/apppend + set</td><td>100</td><td>0.004</td><td>0.001</td><td></td></tr> -<tr><td>pre/append with values</td><td>100</td><td>0.003</td><td>0.000</td><td></td></tr> -<tr><td>binary search</td><td>100</td><td>n/a</td><td>0.000</td><td>100</td></tr> -<tr><td> </td><td></td><td></td><td></td><td></td></tr> <tr><td>pre/apppend + set</td><td>250</td><td>0.019</td><td>0.003</td><td></td></tr> <tr><td>pre/append with values</td><td>250</td><td>0.015</td><td>0.001</td><td></td></tr> <tr><td>binary search</td><td>250</td><td>n/a</td><td>0.000</td><td>250</td></tr> -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>pre/apppend + set</td><td>500</td><td>0.068</td><td>0.007</td><td></td></tr> -<tr><td>pre/append with values</td><td>500</td><td>0.054</td><td>0.003</td><td></td></tr> -<tr><td>binary search</td><td>500</td><td>n/a</td><td>0.000</td><td>500</td></tr> -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>pre/apppend + set</td><td>1000</td><td>0.225</td><td>0.015</td><td></td></tr> -<tr><td>pre/append with values</td><td>1000</td><td>0.203</td><td>0.006</td><td></td></tr> -<tr><td>binary search</td><td>1000</td><td>n/a</td><td>0.001</td><td>1000</td></tr> +<tr><td>unsorted store search</td><td>250</td><td>0.031</td><td>0.003</td><td>250</td></tr> <tr><td> </td><td></td><td></td><td></td><td></td></tr> <tr><td>pre/apppend + set</td><td>2500</td><td>1.474</td><td>0.044</td><td></td></tr> <tr><td>pre/append with values</td><td>2500</td><td>1.324</td><td>0.015</td><td></td></tr> <tr><td>binary search</td><td>2500</td><td>n/a</td><td>0.002</td><td>2500</td></tr> -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>pre/apppend + set</td><td>5000</td><td>6.432</td><td>0.115</td><td></td></tr> -<tr><td>pre/append with values</td><td>5000</td><td>5.624</td><td>0.035</td><td></td></tr> -<tr><td>binary search</td><td>5000</td><td>n/a</td><td>0.004</td><td>5000</td></tr> -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>pre/apppend + set</td><td>10000</td><td>26.967</td><td>0.335</td><td></td></tr> -<tr><td>pre/append with values</td><td>10000</td><td>23.803</td><td>0.081</td><td></td></tr> -<tr><td>binary search</td><td>10000</td><td>n/a</td><td>0.009</td><td>10000</td></tr> +<tr><td>unsorted store search</td><td>2500</td><td>0.340</td><td>0.028</td><td><i>250</i></td></tr>
-<tr><td> </td><td></td><td></td><td></td><td></td></tr> +<tr><td colspan="5" class="empty"> </td></tr> <tr><th>Store sorted by string</th><th>Row count</th><th>GtkTreeStore</th> <th>ScpTreeStore</th><th>Times</th></tr> <tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>pre/apppend + set</td><td>25</td><td>0.003</td><td>0.001</td><td></td></tr> -<tr><td>pre/append with values</td><td>25</td><td>0.001</td><td>0.001</td><td></td></tr> -<tr><td>binary search</td><td>25</td><td>n/a</td><td>0.000</td><td>25</td></tr> -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>pre/apppend + set</td><td>100</td><td>0.014</td><td>0.005</td><td></td></tr> -<tr><td>pre/append with values</td><td>100</td><td>0.014</td><td>0.003</td><td></td></tr> -<tr><td>binary search</td><td>100</td><td>n/a</td><td>0.002</td><td>100</td></tr> -<tr><td> </td><td></td><td></td><td></td><td></td></tr> <tr><td>pre/apppend + set</td><td>250</td><td>0.092</td><td>0.015</td><td></td></tr> <tr><td>pre/append with values</td><td>250</td><td>0.093</td><td>0.009</td><td></td></tr> <tr><td>binary search</td><td>250</td><td>n/a</td><td>0.006</td><td>250</td></tr> -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>pre/apppend + set</td><td>500</td><td>0.366</td><td>0.034</td><td></td></tr> -<tr><td>pre/append with values</td><td>500</td><td>0.343</td><td>0.021</td><td></td></tr> -<tr><td>binary search</td><td>500</td><td>n/a</td><td>0.012</td><td>500</td></tr> -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>pre/apppend + set</td><td>1000</td><td>1.415</td><td>0.077</td><td></td></tr> -<tr><td>pre/append with values</td><td>1000</td><td>1.444</td><td>0.047</td><td></td></tr> -<tr><td>binary search</td><td>1000</td><td>n/a</td><td>0.028</td><td>1000</td></tr> +<tr><td>unsorted store search</td><td>250</td><td>0.224</td><td>0.183</td><td>250</td></tr> <tr><td> </td><td></td><td></td><td></td><td></td></tr> <tr><td>pre/apppend + set</td><td>2500</td><td>9.032</td><td>0.229</td><td></td></tr> <tr><td>pre/append with values</td><td>2500</td><td>9.061</td><td>0.134</td><td></td></tr> <tr><td>binary search</td><td>2500</td><td>n/a</td><td>0.080</td><td>2500</td></tr> -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>pre/apppend + set</td><td>5000</td><td>36.648</td><td>0.521</td><td></td></tr> -<tr><td>pre/append with values</td><td>5000</td><td>38.045</td><td>0.296</td><td></td></tr> -<tr><td>binary search</td><td>5000</td><td>n/a</td><td>0.177</td><td>5000</td></tr> -<tr><td> </td><td></td><td></td><td></td><td></td></tr> -<tr><td>pre/apppend + set</td><td>10000</td><td>slow</td><td>1.225</td><td></td></tr> -<tr><td>pre/append with values</td><td>10000</td><td>slow</td><td>0.654</td><td></td></tr> -<tr><td>binary search</td><td>10000</td><td>n/a</td><td>0.385</td><td>10000</td></tr> - +<tr><td>unsorted store search</td><td>2500</td><td>2.273</td><td>1.859</td><td><i>250</i></td></tr> </table>
-<p>pre/append = prepend for GtkTreeStore (faster than append) and append for ScpTreeStore -(faster than prepend)<br> -all defensive checks enabled, all string tests with utf8 collation</p> - -<p>The difference is easy to explain. First, GtkTreeStore often converts values between their -internal store presentation and GValue, duplicating strings and referencing objects. Second, -binary vs. linear search. Third, invoking the GtkTreeModel implementation functions directly -makes a difference for a lot of calls. Fourth, GtkTreeStore uses lists to keep the row values -and column sort headers, but the columns are arways referenced by index. By itself, inserting -into and removing from a list should be faster than the same array operations. But the store -operations must emit a signal, containing the row path (index), which negates this advantage. -</p> +<p>The full speed test is <a href="fullspeed.html">here</a>. In general, a sorted ScpTreeStore +can be used as a normal data structure, which is not the case with GtkTree/ListStore.</p>
<hr>
@@ -689,10 +503,10 @@
<p><b>GtkTreeStore, Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford</b></p>
-<p>ScpTreeStore was initially written for the Scope plugin of Geany light IDE, which relies -heavily on stores.</p> +<p>ScpTreeStore was written for the Scope plugin of Geany light IDE, which relies heavily on +stores.</p>
-<p><b>ScpTreeStore 0.84, Copyright (C) 2013 Dimitar Toshkov Zhekov</b></p> +<p><b>ScpTreeStore 0.85, Copyright (C) 2013 Dimitar Toshkov Zhekov</b></p>
<p>ScpTreeStore is distributed under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any
Modified: scope/src/thread.c 13 files changed, 4 insertions(+), 9 deletions(-) =================================================================== @@ -172,10 +172,10 @@ static void auto_select_thread(void) } }
-guint thread_count; -const char *thread_id; -ThreadState thread_state; -guint thread_prompt; +guint thread_count = 0; +const char *thread_id = NULL; +ThreadState thread_state = THREAD_BLANK; +guint thread_prompt = 0;
const char *thread_group_id(void) { @@ -876,11 +876,6 @@ void thread_init(void) GtkTreeView *tree = view_create("thread_view", &store, &selection); GtkWidget *menu = menu_select("thread_menu", &thread_menu_info, selection);
- thread_count = 0; - thread_id = NULL; - thread_state = THREAD_BLANK; - thread_prompt = 0; - view_set_sort_func(store, THREAD_ID, store_gint_compare); view_set_sort_func(store, THREAD_FILE, store_seek_compare); view_set_line_data_func("thread_line_column", "thread_line", THREAD_LINE);
Modified: scope/src/tooltip.c 20 files changed, 6 insertions(+), 14 deletions(-) =================================================================== @@ -48,9 +48,9 @@ static void tooltip_trigger(void) } }
-static gchar *output; -static gint last_pos; -static gint peek_pos; +static gchar *output = NULL; +static gint last_pos = -1; +static gint peek_pos = -1; static gboolean show;
static void tooltip_set(gchar *text) @@ -69,7 +69,7 @@ static void tooltip_set(gchar *text) } }
-static gint scid_gen; +static gint scid_gen = 0;
void on_tooltip_error(GArray *nodes) { @@ -86,7 +86,7 @@ void on_tooltip_error(GArray *nodes) } }
-static char *input; +static char *input = NULL;
void on_tooltip_value(GArray *nodes) { @@ -97,7 +97,7 @@ void on_tooltip_value(GArray *nodes) } }
-static guint query_id; +static guint query_id = 0;
static gboolean tooltip_launch(gpointer gdata) { @@ -200,14 +200,6 @@ gboolean tooltip_update(void) return TRUE; }
-void tooltip_init(void) -{ - output = NULL; - tooltip_clear(); - input = NULL; - query_id = 0; -} - void tooltip_finalize(void) { g_free(output);
Modified: scope/src/tooltip.h 1 files changed, 0 insertions(+), 1 deletions(-) =================================================================== @@ -28,7 +28,6 @@ void tooltip_clear(void); gboolean tooltip_update(void);
-void tooltip_init(void); void tooltip_finalize(void);
#define TOOLTIP_H 1
Modified: scope/src/views.c 27 files changed, 12 insertions(+), 15 deletions(-) =================================================================== @@ -50,7 +50,7 @@ { FALSE, VC_FRAME, watches_clear, watches_update, FALSE, DS_VARIABLE }, { FALSE, VC_DATA, memory_clear, memory_update, FALSE, DS_VARIABLE }, { FALSE, VC_NONE, NULL, dc_update, FALSE, DS_DEBUG }, - { FALSE, VC_FRAME, inspects_clear, inspects_update, FALSE, DS_DEBUG }, + { FALSE, VC_FRAME, inspects_clear, inspects_update, FALSE, DS_VARIABLE }, { FALSE, VC_FRAME, registers_clear, registers_update, TRUE, DS_DEBUG }, { FALSE, VC_DATA, tooltip_clear, tooltip_update, FALSE, DS_SENDABLE }, { FALSE, VC_NONE, menu_clear, NULL, FALSE, 0 } @@ -114,7 +114,11 @@ void views_context_dirty(DebugState state, gboolean frame_only) } }
-static ViewIndex view_current; +#ifdef G_OS_UNIX +static ViewIndex view_current = VIEW_TERMINAL; +#else +static ViewIndex view_current = VIEW_THREADS; +#endif
void views_clear(void) { @@ -579,18 +583,18 @@ gboolean view_command_active(void) return gtk_widget_get_visible(command_dialog); }
-static DebugState last_views_state; - void views_update_state(DebugState state) { - if (state != last_views_state) + static DebugState last_state = 0; + + if (state != last_state) { if (gtk_widget_get_visible(command_dialog)) command_line_update_state(state); locals_update_state(state); watches_update_state(state); inspects_update_state(state); - last_views_state = state; + last_state = state; } }
@@ -604,15 +608,8 @@ static void on_geany_sidebar_switch_page(G_GNUC_UNUSED GtkNotebook *notebook,
void views_init(void) { -#ifdef G_OS_UNIX - view_current = VIEW_TERMINAL; -#else - view_current = VIEW_THREADS; -#endif - last_views_state = 0; - - if (!pref_var_update_bug) - views[VIEW_INSPECT].state = DS_VARIABLE; + if (pref_var_update_bug) + views[VIEW_INSPECT].state = DS_DEBUG;
command_dialog = dialog_connect("command_dialog"); command_view = get_widget("command_view");
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).