Re: [gtk-list] RFC: gtk-thread.c



Hi, Erik 

> In addition to my gtk-fork example I posted to this list a month ago,
> I now made a GTK + threads example. This is also my first multi-threaded
> program, so please tell me about errors. I tested this on Linux only,
> so maybe it is not completely portable.

I would explicitly lock the yes_or_no variable. Its an example and thus should
protect global vars properly, even though this special example could do
without (as it wouldn't hurt semantics (just do something), if there weren't a
lock ;-). It would look something like that then:

---- 8< ---- 8< ---- end gtk-thread.c ---- 8< ---- 8< ----
/*-------------------------------------------------------------------------
 * Filename:      gtk-thread.c
 * Version:       0.99.1
 * Copyright:     Copyright (C) 1999, Erik Mouw
 * Author:        Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
 * Description:   GTK threads example
 * Created at:    Sun Oct 17 21:27:09 1999
 * Modified by:   Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
 * Modified at:   Sun Oct 24 17:28:50 1999
 *-----------------------------------------------------------------------*/
/*
 * Compile with:
 *
 * cc -o gtk-thread gtk-thread.c `gtk-config --cflags --libs gthread`
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <gtk/gtk.h>
#include <glib.h>
#include <pthread.h>




#define YES_IT_IS    (1)
#define NO_IT_IS_NOT (0)




typedef struct 
{
  GtkWidget *label;
  int what;
} yes_or_no_args;



G_LOCK_DEFINE_STATIC (yes_or_no);
static volatile int yes_or_no = YES_IT_IS;




gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
  return(FALSE);
}




void destroy(GtkWidget *widget, gpointer data)
{
  gtk_main_quit();
}




void *argument_thread(void *args)
{
  yes_or_no_args *data = (yes_or_no_args *)args;
  gboolean say_something;

  for(;;)
    {
      /* sleep a while */
      sleep(rand() / (RAND_MAX / 3) + 1);

      /* Lock the yes_or_no variable */
      G_LOCK(yes_or_no);

      /* do we have to say something? */
      say_something = (yes_or_no != data->what);
      
      if(say_something)
	{
	  /* set the variable */
	  yes_or_no = data->what;
	}

      /* Unlock the yes_or_no variable */
      G_UNLOCK(yes_or_no);

      if(say_something)
	{
          /* get GTK thread lock */
          gdk_threads_enter();

          /* set label text */
          if(data->what == YES_IT_IS)
            gtk_label_set_text(GTK_LABEL(data->label), "O yes, it is!");
          else
            gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!");

          /* release GTK thread lock */
          gdk_threads_leave();
        }
    }

  return(NULL);
}




int main(int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *label;
  yes_or_no_args yes_args, no_args;
  pthread_t no_tid, yes_tid;

  /* init threads */
  g_thread_init(NULL);

  /* init gtk */
  gtk_init(&argc, &argv);

  /* init random number generator */
  srand((unsigned int)time(NULL));

  /* create a window */
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  
  gtk_signal_connect(GTK_OBJECT (window), "delete_event",
                     GTK_SIGNAL_FUNC(delete_event), NULL);
          
  gtk_signal_connect(GTK_OBJECT (window), "destroy",
                     GTK_SIGNAL_FUNC(destroy), NULL);

#if (GTK_MAJOR_VERSION == 1) && (GTK_MINOR_VERSION == 0)
  gtk_container_border_width(GTK_CONTAINER (window), 10);
#else  
  gtk_container_set_border_width(GTK_CONTAINER (window), 10);
#endif

  /* create a label */
  label = gtk_label_new("And now for something completely different ...");
  gtk_container_add(GTK_CONTAINER(window), label);
  
  /* show everything */
  gtk_widget_show(label);
  gtk_widget_show (window);

  /* create the threads */
  yes_args.label = label;
  yes_args.what = YES_IT_IS;
  pthread_create(&yes_tid, NULL, argument_thread, &yes_args);

  no_args.label = label;
  no_args.what = NO_IT_IS_NOT;
  pthread_create(&no_tid, NULL, argument_thread, &no_args);

  /* enter the GTK main loop */
  gdk_threads_enter();
  gtk_main();
  gdk_threads_leave();

  return(0);
}
---- 8< ---- 8< ---- end gtk-thread.c ---- 8< ---- 8< ----

Other than that its ok, AFAICT.

Bye,
Sebastian
-- 
Sebastian Wilhelmi                   |            här ovanför alla molnen
mailto:wilhelmi@ira.uka.de           |      är himmlen så förunerligt blå
http://goethe.ira.uka.de/~wilhelmi   |



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