From: short <> Date: Sun, 26 Oct 2003 19:07:18 +0000 (+0000) Subject: GnomeUI responsiveness fixed by multithreading. X-Git-Tag: captive-1_0_1~30 X-Git-Url: http://git.jankratochvil.net/?p=captive.git;a=commitdiff_plain;h=b1e7491c03292459c113166b1d55ae94797fa723 GnomeUI responsiveness fixed by multithreading. PROGRESS_UPDATE_USEC: 100000 -> 200000 Accelerate ProgressBar during .CAB header parsing: respect PROGRESS_UPDATE_USEC. --- diff --git a/src/install/acquire/ui-gnome.c b/src/install/acquire/ui-gnome.c index 12819a8..1fa0dba 100644 --- a/src/install/acquire/ui-gnome.c +++ b/src/install/acquire/ui-gnome.c @@ -41,7 +41,7 @@ /* Config: */ -#define PROGRESS_UPDATE_USEC 100000 +#define PROGRESS_UPDATE_USEC 200000 static GnomeApp *App; @@ -143,6 +143,8 @@ GtkTreeIter *iter; g_return_if_fail(module_type!=NULL); + gdk_threads_enter(); + iter=DriversTreeStore_Iter_hash_get_iter(module_type); gtk_tree_store_set(DriversTreeStore,iter, DRIVERS_TREE_STORE_COLUMN_TYPE,module_type, @@ -153,6 +155,9 @@ GtkTreeIter *iter; ? _("NOT FOUND; essential module for NTFS disks access") : _("not found; optional module")), -1); + + gdk_flush(); + gdk_threads_leave(); } static void ui_gnome_module_available_notify(struct module_available *module_available) @@ -164,6 +169,8 @@ static gboolean some_module_ntfs_sys_found=FALSE; g_return_if_fail(module_available!=NULL); g_return_if_fail(module_available->module!=NULL); + gdk_threads_enter(); + iter=DriversTreeStore_Iter_hash_get_iter(module_available->module->type); gtk_tree_store_set(DriversTreeStore,iter, DRIVERS_TREE_STORE_COLUMN_TYPE,module_available->module->type, @@ -177,19 +184,28 @@ static gboolean some_module_ntfs_sys_found=FALSE; some_modules_found=some_module_ntoskrnl_exe_found && some_module_ntfs_sys_found; state_changed(); + + gdk_flush(); + gdk_threads_leave(); } static gboolean all_modules_found=FALSE; static void ui_gnome_all_modules_found_notify(void) { + gdk_threads_enter(); + all_modules_found=TRUE; state_changed(); + + gdk_flush(); + gdk_threads_leave(); } static gboolean aborted=FALSE; static gboolean aborted_back=FALSE; /* 'Back' button was clicked. */ static struct timeval ProgressEntry_updated_timeval; +static struct timeval ProgressBar_updated_timeval; static void progress_start(void) { @@ -197,6 +213,7 @@ static void progress_start(void) aborted=FALSE; aborted_back=FALSE; CAPTIVE_MEMZERO(&ProgressEntry_updated_timeval); + CAPTIVE_MEMZERO(&ProgressBar_updated_timeval); state_changed(); } @@ -206,10 +223,30 @@ static void progress_end(void) state_changed(); } +static gboolean want_progress_update(struct timeval *timeval) +{ +struct timeval now_timeval; +struct timeval diff_timeval; + + g_return_val_if_fail(timeval!=NULL,FALSE); + + gettimeofday( /* FIXME: errors ignored */ + &now_timeval, /* tv */ + NULL); /* tz */ + timersub(&now_timeval,timeval,&diff_timeval); + if (!timeval->tv_sec || diff_timeval.tv_sec>0 || diff_timeval.tv_usec>=PROGRESS_UPDATE_USEC) { + *timeval=now_timeval; + return TRUE; + } + return FALSE; +} + static gboolean ui_gnome_progress(GnomeVFSURI *uri) { /* 'uri' may be NULL */ + gdk_threads_enter(); + if (ProgressEntry) { static gchar *uri_text=NULL; @@ -223,22 +260,18 @@ static gchar *uri_text=NULL; } if (uri_text) { -struct timeval now_timeval; -struct timeval diff_timeval; - - gettimeofday( /* FIXME: errors ignored */ - &now_timeval, /* tv */ - NULL); /* tz */ - timersub(&now_timeval,&ProgressEntry_updated_timeval,&diff_timeval); - if (!ProgressEntry_updated_timeval.tv_sec || diff_timeval.tv_sec>0 || diff_timeval.tv_usec>=PROGRESS_UPDATE_USEC) { + if (want_progress_update(&ProgressEntry_updated_timeval)) gtk_entry_set_text(ProgressEntry, uri_text+(strncmp(uri_text,"file://",strlen("file://")) ? 0 : strlen("file://"))); - ProgressEntry_updated_timeval=now_timeval; - } } } - while (gtk_events_pending()) - gtk_main_iteration(); + + gdk_flush(); + gdk_threads_leave(); + + /* Do not: g_thread_yield(); + * as it is TOO much expensive and we are multithreaded anyway. + */ if (aborted) return TRUE; @@ -253,21 +286,30 @@ static void ui_gnome_progress_bar(gint done,gint length) g_return_if_fail(done>=0); g_return_if_fail(length>=0); + if (!want_progress_update(&ProgressBar_updated_timeval)) + return; + + gdk_threads_enter(); + if (!length) { gtk_progress_bar_pulse(MicrosoftComProgress); gtk_progress_bar_set_text(MicrosoftComProgress,""); } else { -gchar *done_display,*length_display; +gchar *length_display; + /* Do not format 'done' by gnome_vfs_format_file_size_for_display() + * as the progress would not be visible for large 'done' sizes. + */ gtk_progress_bar_set_fraction(MicrosoftComProgress,((gdouble)done)/length); - done_display=gnome_vfs_format_file_size_for_display(done); length_display=gnome_vfs_format_file_size_for_display(length); gtk_progress_bar_set_text(MicrosoftComProgress, - captive_printf_alloca("%s / %s",done_display,length_display)); - g_free(done_display); + captive_printf_alloca("%d B / %s",(int)done,length_display)); g_free(length_display); } + + gdk_flush(); + gdk_threads_leave(); } /* FIXME: Change it to "prepare" signal. */ @@ -333,6 +375,66 @@ gchar *text; gtk_widget_thaw_child_notify(vbox_widget); } +typedef void (*process_t)(void); + +/* 'GThreadFunc' type. */ +gpointer execute_process_func(process_t process /* data */) +{ + (*process)(); + + gdk_threads_enter(); + + gtk_main_quit(); /* Abort gtk_main() of execute_process(). */ + + gdk_flush(); + gdk_threads_leave(); + + return NULL; +} + +/* We are called inside gdk_threads_enter(). */ +static void execute_process(process_t process) +{ +GThread *gthread; + + progress_start(); + gthread=g_thread_create_full( + (GThreadFunc)execute_process_func, /* func */ + process, /* data */ + 0, /* stack_size; 0 means the default size */ + TRUE, /* joinable */ + TRUE, /* bound; use system thread */ + G_THREAD_PRIORITY_LOW, /* priority; G_THREAD_PRIORITY_LOW is the lowest one */ + NULL); /* error */ + gtk_main(); /* We are already called inside gdk_threads_enter(). */ + /* I hope some other gtk_main_quit() did not occur as we would + * locked if the 'process' func did not finish yet. + */ + g_thread_join(gthread); + progress_end(); +} + +/* 'process_t' typed. */ +static void process_scan_disk(void) +{ + scan_disks_quick(); + scan_disks(); +} + +static GnomeVFSURI *process_scan_path_scan_path_uri; + +/* 'process_t' typed. */ +static void process_scan_path(void) +{ + mod_uri_load(process_scan_path_scan_path_uri); +} + +/* 'process_t' typed. */ +static void process_microsoft_com(void) +{ + microsoft_com(); +} + gboolean on_Page_next(GnomeDruidPage *gnomedruidpage,GtkWidget *widget,gpointer user_data /* unused */) { g_return_val_if_fail(GNOME_IS_DRUID_PAGE(gnomedruidpage),FALSE); @@ -347,10 +449,7 @@ gboolean on_Page_next(GnomeDruidPage *gnomedruidpage,GtkWidget *widget,gpointer } } else if (page_active==ScanDiskPage) { - progress_start(); - scan_disks_quick(); - scan_disks(); - progress_end(); + execute_process(process_scan_disk); if (aborted_back) { gnome_druid_set_page(Druid,PageStart); return TRUE; /* ignore button press */ @@ -368,9 +467,8 @@ const gchar *scan_path_uri_text=gtk_entry_get_text(ScanPathLocationComboEntry); GnomeVFSURI *scan_path_uri; if ((scan_path_uri=gnome_vfs_uri_new(scan_path_uri_text))) { - progress_start(); - mod_uri_load(scan_path_uri); - progress_end(); + process_scan_path_scan_path_uri=scan_path_uri; + execute_process(process_scan_path); gnome_vfs_uri_unref(scan_path_uri); if (aborted_back) { gnome_druid_set_page(Druid,(all_modules_found ? PageStart : ScanDiskPage)); @@ -402,9 +500,7 @@ void on_MicrosoftComConfirmButton_clicked(GtkButton *button,gpointer user_data) if (page_active!=MicrosoftComPage) /* bogus callback */ return; - progress_start(); - microsoft_com(); - progress_end(); + execute_process(process_microsoft_com); if (aborted_back) { gnome_druid_set_page(Druid,(all_modules_found ? PageStart : ScanPathPage)); return; @@ -588,6 +684,8 @@ GtkWidget *dialog; if (in_progress && aborted) return; + gdk_threads_enter(); + /**/ if (log_level & G_LOG_LEVEL_ERROR) dialog=gnome_app_error(App,message); else if (log_level & (G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING)) @@ -599,12 +697,23 @@ GtkWidget *dialog; g_signal_connect((gpointer)dialog,"close",G_CALLBACK(gtk_main_quit),NULL); gtk_main(); /* 'dialog' gets destroyed automatically */ + + gdk_flush(); + gdk_threads_leave(); } static void ui_gnome_interactive(void) { gtk_widget_show_all(GTK_WIDGET(App)); + + if (!g_thread_supported()) + g_thread_init(NULL); + if (!gdk_threads_mutex) + gdk_threads_init(); + + gdk_threads_enter(); gtk_main(); + gdk_threads_leave(); exit(EXIT_SUCCESS); }