Re: GTK+ app hang on win32
- From: todd <toddf simosoftware com>
- To: Dave Andruczyk <djandruczyk yahoo com>
- Cc: gtk-app-devel-list gnome org
- Subject: Re: GTK+ app hang on win32
- Date: Sun, 05 Dec 2004 14:54:07 -0800
win32 doesn't support multiple threads in this way and in fact it is not
safe to do this in linux either.
You should use a GAsyncQueue to notify the main thread, which perhaps
has a timeout function listening for such requests or
better makes use of GSource. I know there was discussion about this on
the list earlier this year. But incase that has become
difficult to find here's example I created.
-todd
Dave Andruczyk wrote:
I've gotten my application to run on windows (Was natively linux) and have hit
several problems...
1. My app pops up a dialog window in the case of a problem. (i.e. can't talk
to a remote device). in linux this works perfectly, in windows it pops up a
blank window and the cursor changes to an hourglass when that window has the
focus
2. As my app is running, it uses glade to load various tabs into a global
gtk_notebook. after each glade file is processed, it tries to call
gtk_notebook_append_page() and under win32 this call HANGS indefinitely, task
manager reports 0% cpu usage, so it doesn't appear to be stuck in a race)
NOTE regarding #2. the tab loading is run from within a thread that is wrapped
by calls to gdk_threads_enter() and gdk_threads_leave(). This works flawlessly
on linux, freebsd and OS-X, but hangs at the above location on windows (Win2k
SP4). Is this a GTK+ bug in the gtk_notebook or glib itself on win32?
I'm using gtk-win32-2.4.14-rc1, and libglade-2.4.0 from the
gladewin32.sourceforge.net site.
=====
Dave J. Andruczyk
__________________________________
Do you Yahoo!?
The all-new My Yahoo! - What will yours do?
http://my.yahoo.com
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list gnome org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
#include <gtk/gtk.h>
#include <glade/glade.h>
typedef struct _Prog Prog;
struct _Prog{
GSource source;
gint counter;
gint update;
/* do not access from thread */
GtkWidget *progress;
};
static gboolean run_prepare( GSource *src, gint *timeout );
static gboolean run_check( GSource *src );
static gboolean run_dispatch( GSource *src, GSourceFunc callback, gpointer usr_data );
static gboolean run_callback( gpointer data );
static void dolotsofwork( Prog *prog );
static void reset( GtkWidget *button, Prog *prog );
static void shutdown( GtkObject *obj, Prog *prog )
{
gint *count = &(prog->counter);
gint *notify = &(prog->update);
g_atomic_int_exchange_and_add( count, 100 + ( g_atomic_int_get( count ) * -1 ) );
g_atomic_int_compare_and_exchange( notify, 0, 1 );
gtk_main_quit();
}
int main( int argc, char **argv )
{
GSourceFuncs funcs = { run_prepare, run_check, run_dispatch, 0 };
Prog *src = (Prog*)g_source_new( &funcs, sizeof( Prog ) );
GladeXML *xml;
GThread *tid;
GError *error = 0;
src->counter = 0;
src->update = 0;
gtk_rc_add_default_file( "gtkrc" );
g_thread_init(NULL);
gtk_init( &argc, &argv );
xml = glade_xml_new( "events.glade", 0, 0 );
if( xml == 0 ){
return 1;
}
src->progress = glade_xml_get_widget( xml, "progressbar1" );
glade_xml_signal_connect_data( xml, "on_window1_destroy", G_CALLBACK( shutdown ), src );
glade_xml_signal_connect_data( xml, "on_button1_clicked", G_CALLBACK( reset ), src );
g_object_unref( xml );
g_source_set_callback( (GSource*)src, (GSourceFunc)run_callback, src, 0 );
g_source_attach( (GSource*)src, g_main_context_default() );
tid = g_thread_create( (GThreadFunc)dolotsofwork, src, FALSE, &error );
if( !tid || error ){
g_printerr( "Error creating thread: %s\n", error->message );
g_error_free( error );
return 1;
}
gtk_main();
g_source_destroy( (GSource*)src );
return 0;
}
static void
reset( GtkWidget *button, Prog *prog )
{
gint *count = &(prog->counter);
gint *notify = &(prog->update);
g_atomic_int_exchange_and_add( count, g_atomic_int_get( count ) * -1 );
g_atomic_int_compare_and_exchange( notify, 0, 1 );
}
static void
dolotsofwork( Prog *prog )
{
guint i;
gint *counter = &prog->counter;
gint *notify = &prog->update;
for( i = 0; i < 100; i = g_atomic_int_exchange_and_add( counter, 1 ) ){
g_atomic_int_compare_and_exchange( notify, 0, 1 );
g_usleep( 100000 );
}
}
static gboolean
run_callback( gpointer data )
{
Prog *prog = (Prog*)data;
gint *tmp = &(prog->counter);
gint *notify = &(prog->update);
gdouble counter = (gdouble)g_atomic_int_get( tmp );
GtkProgressBar *progress = GTK_PROGRESS_BAR( prog->progress );
gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR( progress ), counter / 100.0 );
g_atomic_int_compare_and_exchange( notify, 1, 0 );
if( counter >= 99.999 )
g_print( "done\n" );
return counter < 99.999;
}
static gboolean
run_prepare( GSource *src, gint *timeout )
{
*timeout = 10;
return run_check( src );
// return true if ready
}
static gboolean
run_check( GSource *src )
{
Prog *prog = (Prog*)src;
gint *tmp = &(prog->update);
// return true if ready
return g_atomic_int_get( tmp );
}
static gboolean
run_dispatch( GSource *src, GSourceFunc callback, gpointer usr_data )
{
// call the callback
//
// return false if done
return callback( usr_data );
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]