CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    GTK - ensuring safe communication with GUI objects.

    Let's take a typical Windows scenario (just for comparison). We have a dialog box with a button and progress bar. When the button gets pressed it starts a worker thread. The worker thread needs to update the progress bar periodically. Because Windows is a message driven architecture we can simply pass the dialog's handle to the worker thread - and then the thread can send messages to the dialog box as necessary, telling it to update its progress bar. Because the messages are received in the GUI thread, this guarantees that any updates for GUI objects will always take place in the GUI thread.

    But GTK isn't message driven - it's driven by events and signals. So the worker thread either needs a pointer to the progress bar or a way to emit a signal when the bar needs to be updated. For example, if we provide the worker thread with a pointer, something as simple as this will theoretically update the progress bar:-

    Code:
    	pProgressBar->set_fraction(required_value); // 'pProgressBar' is a pointer passed from the GUI thread
    Although the above does work, it seems to be very unreliable and prone to crashing, especially if something else needs to control the progress bar simultaneously - e.g. if the dialog box happens to be getting dragged or resized whilst the worker thread is running.

    Clearly we need some system to ensure that GUI updates can only take place in the GUI thread.. What's the solution to this in a non message driven architecture?
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  2. #2
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: GTK - ensuring safe communication with GUI objects.

    Well, GTK does include synchronization mechanisms, but I found them to be a half-measure which didn't always work.

    The approach I ended up using, which seemed to work well but is perhaps a bit inelegant, is to provide two versions of any function which needs to modify a GUI element: one which may only be called from the event loop thread, and one which can be called from any thread. Then I'd relate them as such:

    Code:
    gboolean doUpdate(gpointer data)
    {
         ArgsType *args = (ArgsType*)data;
         // Processing
    }
    
    void update(ArgsType *args)
    {
         g_idle_add(doUpdate, args);
    }
    In the event synchronous behavior was needed, I would do something fancier like
    Code:
    gboolean doUpdate(gpointer data)
    {
         ArgsType *args = (ArgsType*)data;
         // Processing
         signal(condition);
    }
    
    void update(ArgsType *args)
    {
         if (pthread_equal(eventthread, pthread_self()))
              doUpdate(args);
         else
         {
              g_idle_add(doUpdate, args);
              wait(condition);
         }
    }
    Obviously one of the args fields could be used to differentiate whether that *particular* invokation was completed on the condition signal, if further necessary.
    Last edited by Lindley; February 8th, 2010 at 02:12 PM.

  3. #3
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: GTK - ensuring safe communication with GUI objects.

    Thanks for the suggestion Lindley but to my amazement, I can't seem to make it work. This statement:-

    Code:
    g_idle_add(doUpdate, args);
    seems to schedule the function for processing during the idle time for the current thread. So if I do something like that in a worker thread, the call to doUpdate() will get delayed until there's some idle time available - but it will still get executed in the worker thread. I discovered this by setting up two global variables; one to save the ID for the GUI thread and another to save the ID for the worker thread. Then, within my doUpdate() function, I called pthead_self() to find out which thread was being executed. It turns out to be whichever thread called g_idle_add() in the first place. Admittedly, I was using g_idle_add_full() because I wanted to tinker with the priority settings but I guess the effect would be the same for both versions.
    Last edited by John E; February 9th, 2010 at 05:41 AM.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  4. #4
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: GTK - ensuring safe communication with GUI objects.

    That's really strange. It definitely doesn't call it in the worker thread in my code. Perhaps ask on the GTK mailing list?

  5. #5
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: GTK - ensuring safe communication with GUI objects.

    Thanks. One thing that's probably significant is that I'm using the Win32 version of GTK. Maybe I should try compiling the same app for Linux and see what heppens there. I'll let you know..!
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  6. #6
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: GTK - ensuring safe communication with GUI objects.

    Well, I was targeting both Linux and Win32, which is why I chose that approach to begin with (the GTK mutexes are, or at least were, broken on Win32). So I don't know what to tell you. Double-check that your "which thread am I in" check is correct?

  7. #7
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: GTK - ensuring safe communication with GUI objects.

    Lindley - are you still able to build gtk apps using gtk-win32 (and which compiler were you using)?

    The reason I'm asking is that I rebuilt my test app under Linux and Cygwin, both of which use gcc. Both versions worked as you described (i.e. the idle processing took place in the GUI thread). But when I compile it using VC++2005 and gtk-win32, the processing gets done in the wrong thread. I'm talking to someone on the gtk-win32 mailing list at the moment but he reckons it's impossible for this to go wrong. However, my current theory is that it's probably only ever been tested with MinGW and probably not with VC++.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  8. #8
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: GTK - ensuring safe communication with GUI objects.

    I was using VS2005, so that's not it.

    Make sure you're calling g_thread_init() early in the program, probably just after gtk_init(). That's all I can think of which might affect it.

  9. #9
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: GTK - ensuring safe communication with GUI objects.

    Quote Originally Posted by Lindley View Post
    Make sure you're calling g_thread_init() early in the program, probably just after gtk_init(). That's all I can think of which might affect it.
    An excellent suggestion Lindley. I wasn't calling g_thread_init() at all (it didn't occur to me that I'd need it, since I'm using pthreads). However, adding that call has immediately fixed the problem. Many thanks!
    "A problem well stated is a problem half solved.” - Charles F. Kettering

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured