Re: Problems with Threading Concept



On Mon, 2007-02-19 at 12:42 +0530, naveen wrote:

#include <gtk/gtk.h>
#include "stdio.h"
#include <pthread.h>

 int flag=1,toggle=0;
    int i=0;
    pthread_t yes_tid; 

void hello()
{

    while (flag)
    {
  gdk_threads_enter ();

      printf ("%d %d\n",i++,flag);
      if (gtk_events_pending())
      gtk_main_iteration(); // Handle unprocessed GTK events

  gdk_threads_leave ();
    }

}

void hello_print( GtkWidget *widget,
            gpointer   data )
{  
   if(toggle==0)
    {
     toggle=1;
     flag=1;
     pthread_create (&yes_tid, NULL,(void *)hello, NULL);
    }
    else
    {
     flag=0;
     toggle=0;
    }

}
int main(int   argc,
          char *argv[] )
{
    
    GtkWidget *window;
    GtkWidget *button;
    g_thread_init (NULL);
    gdk_threads_init ();

  gdk_threads_enter ();

    gtk_init (&argc, &argv);
    
    /* create a new window */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    
    g_signal_connect (G_OBJECT (window), "destroy",
                      G_CALLBACK (gtk_main_quit), NULL);
    
    gtk_container_set_border_width (GTK_CONTAINER (window), 100);
    
    button = gtk_button_new_with_label("click it");
    
    g_signal_connect (G_OBJECT (button), "clicked",
                      G_CALLBACK (hello_print), NULL);
    
    gtk_container_add (GTK_CONTAINER (window), button);
    
    gtk_widget_show (button);
    gtk_widget_show (window);
    
    gtk_main ();

   gdk_threads_leave ();

    return 0;
}



Naveen,
Look at these changes. A B C

A. gdk_thread_enter/leave() is used to surround the gtk_main loop and
any gtk_* functions called from another thread.  In A you are not
calling and gtk_ functions.  I see that you plan too though, when you do
surrond just the group of calls with the gdk_thread... statements.
Also, you should strong consider using g_thread_create() and the glib
set of functions for multithreaded gtk applications.  see "devHelp", a
locally installed api documentation tool, for how-to usage of the glib
functions

B. You have re-implemented the gtk_main() loop here; which is a vaild
construct -just not needed at this level programing.   The gtk_main loop
in the first (main) thread is active and running, trying to handle ALL
gtk commands, this is simply a duplication that adds nothing.

C. In the correct place, immediately before and after, the gtk_main()
these calls serve a vaild function to serialize access to gdk/gtk global
variables.  Managing the resource action will become more difficult when
you start adding more threads or gdk/gtk functions in other threads.
Focus on starting out right and following this before/after guideline
got gtk_main.

General Comment:
The design of a multi-threaded GTK application deserves some time
investment and design consideration.  Read this tutorial link:
"http://www.gtk.org/faq/#AEN482";.    Also, read this for GLIB thread
functions, the preferred choice for GTK multi-threaded programming:
"http://developer.gnome.org/doc/API/2.0/glib/glib-Threads.html";.  

You are going to find very quickly that using gdk/gtk functions in
anything except the main thread is a real pain to control and manage;
BUT it can and has been done by many.  As a design point you should
minimize the need to do so.  Given that: consider this for IO related
thread-like work, GLIB provide the g_io_add_watch()/g_io_channel... set
of functions that are pre-integrated into GTK/GDK cleanly.  For other
programming actions GDK/GTK/GLIB provides a collection of thread-like
constructs to run functions via timers and idles -
g_timeout_add()/g_idle_add().  Most of what I have mentioned thus far
does not require the use of gdk_thread_enter/leave(), and are considered
multi-threaded in behaviour.

Lastly, g_thread_create() and the whole GLIB collection of thread
support routines are available.  As are a collection of inter-thread
communication methods like GASyncQueue(), mutex's, semaphores, and
conditions.   Combined these standard tools and functions will allow you
to create high performance applications that use GDK/GTK graphics
capabilities without hindrance.  Just do a little design work first, and
keep asking questions and looking at existing code that uses these
api's.

James,


#include <gtk/gtk.h>
#include "stdio.h"
#include <pthread.h>

 int flag=1,toggle=0;
    int i=0;
    pthread_t yes_tid; 

void hello()
{

    while (flag)
    {
/*-A  gdk_threads_enter ();   -- your not going gtk thing here so you
don't need this !!  */

      printf ("%d %d\n",i++,flag);

/*-B      if (gtk_events_pending())  -- never do this unless your
certain what your doing */
/*      gtk_main_iteration();         */

/*-A  gdk_threads_leave ();    --- again not needed */
    }

}

void hello_print( GtkWidget *widget,
            gpointer   data )
{  
   if(toggle==0)
    {
     toggle=1;
     flag=1;
     pthread_create (&yes_tid, NULL,(void *)hello, NULL);
    }
    else
    {
     flag=0;
     toggle=0;
    }

}
int main(int   argc,
          char *argv[] )
{
    
    GtkWidget *window;
    GtkWidget *button;
    g_thread_init (NULL);
    gdk_threads_init ();

/*-C  gdk_threads_enter ();   -- too early */

    gtk_init (&argc, &argv);
    
    /* create a new window */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    
    g_signal_connect (G_OBJECT (window), "destroy",
                      G_CALLBACK (gtk_main_quit), NULL);
    
    gtk_container_set_border_width (GTK_CONTAINER (window), 100);
    
    button = gtk_button_new_with_label("click it");
    
    g_signal_connect (G_OBJECT (button), "clicked",
                      G_CALLBACK (hello_print), NULL);
    
    gtk_container_add (GTK_CONTAINER (window), button);
    
    gtk_widget_show (button);
    gtk_widget_show (window);
    
   gdk_threads_enter (); /*-C  -- correct place for this */
    gtk_main ();
   gdk_threads_leave ();

    return 0;
}



James Scott, Jr.                                                 
Registered Linux User #270764
FC6 on Dual AMD-MP 2400+
Author: {gfhcm, gkrellfah2,gapcmon,giw}.sourceforge.net
http://mysite.verizon.net/skoona/index.html


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]