Re: GTK and threads



On Mon, 2006-02-06 at 11:22, Michael Torrie wrote:

I have attached a sample file that uses threads in the way you described 
in your last post.

I generally like to make code examples compile without warning. Did you
even try to compile this?

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

#include <unistd.h> /* sleep() - on Unix, anyway */

gint thread_count=0;
gint dead_threads;

GSList *threads;

struct thread_info_data {
      GtkTextBuffer *buffer;
      gint id;
      pthread_t tid;
      gint terminate;
};

void thread (void *data) {

void * thread(void *data) {

      struct thread_info_data *info;
      GtkTextIter iter;
      GString *message;


      info=(struct thread_info_data *)data;
      message=g_string_new("");

      while(info->terminate == 0 ) {
              sleep(1);
              g_string_printf(message,"Thread %d here.\n",info->id);
              g_print("%s",message->str);
              
              gdk_threads_enter();
              gtk_text_buffer_get_end_iter(info->buffer,&iter);
              gtk_text_buffer_insert(info->buffer,&iter,message->str,-1);
              gdk_threads_leave();
      }
      g_print("Thread %d stopping.\n",info->id);
      gdk_threads_enter(); //borrowing a lock from gtk to lock our variable
      dead_threads++;
      gdk_threads_leave(); //we could and should use a counting semaphore
      g_string_free(message,NULL);

        g_string_free(message,FALSE); /* Hope NULL means FALSE here */
        return 0;
}

void stop_thread(gpointer data, gpointer user_data) {
      struct thread_info_data *thread;

      thread=data;
      thread->terminate=1;
      g_print("Asked thread %d to stop.\n",thread->id);
      
      //here we ought to make sure the thread really has died
//    pthread_join(thread->tid,NULL);
}

void on_destroy(GtkWidget *widget, gpointer data) {
      g_slist_foreach(threads,stop_thread,NULL);

      while(dead_threads < thread_count) {
              while(gtk_events_pending()) {
                      gtk_main_iteration();
              }
              sleep(0);
      }
      gtk_main_quit();
}

void on_button_clicked(GtkWidget *widget, gpointer data) {
      GtkTextBuffer *buffer;
      GtkTextIter iter;
      struct thread_info_data *thread_info;
      
      buffer=GTK_TEXT_BUFFER(data);

      thread_info=g_malloc(sizeof(struct thread_info_data));
      thread_info->buffer=buffer;
      thread_info->id=thread_count++;
      thread_info->terminate=0;

      threads=g_slist_append(threads,thread_info);

      pthread_create(&(thread_info->tid),NULL,thread,thread_info);
      

      gtk_text_buffer_get_end_iter(buffer,&iter);
      gtk_text_buffer_insert(buffer,&iter,"Button clicked!\n",-1);
      g_print("Button clicked.\n");


}


int main(int argc, char *argv[]) {
      GtkWidget *window;
      GtkWidget *button;
      GtkWidget *vbox;
      GtkWidget *viewarea;
      GtkWidget *view;
      GtkWidget *buffer;

        GtkTextBuffer *buffer; /* GtkTextBuffer doesn't inherit from GtkWidget!
*/

      threads=NULL;


      g_thread_init (NULL);
      gdk_threads_init ();

      gtk_init(&argc, &argv);

      window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

      gtk_signal_connect(GTK_OBJECT(window),"destroy",
                         GTK_SIGNAL_FUNC(on_destroy),NULL);
      gtk_container_set_border_width(GTK_CONTAINER(window),10);

      vbox=gtk_vbox_new(FALSE,5);
      gtk_container_add(GTK_CONTAINER(window),vbox);
      gtk_widget_show(vbox);

      viewarea=gtk_scrolled_window_new(NULL,NULL);
      gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(viewarea),
                                     GTK_POLICY_AUTOMATIC,
                                     GTK_POLICY_AUTOMATIC);
      gtk_box_pack_start(GTK_BOX(vbox),viewarea,TRUE,TRUE,2);
      gtk_widget_show(viewarea);
      
      view=gtk_text_view_new();

      buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));

      gtk_text_buffer_set_text(buffer,"The threads will write here.\n",-1);
      gtk_container_add(GTK_CONTAINER(viewarea),view);
      gtk_widget_show(view);
      
      button=gtk_button_new_with_label("Click me");
      gtk_signal_connect(GTK_OBJECT(button),"clicked",
                         GTK_SIGNAL_FUNC(on_button_clicked),buffer);
                         
      gtk_box_pack_end(GTK_BOX(vbox),button,FALSE,FALSE,3);
      
      gtk_widget_show(button);
      gtk_widget_show(window);

      gdk_threads_enter ();
      gtk_main();
      gdk_threads_leave ();

      return 0;
}





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