Re: GTK and threads



Alan M. Evans wrote:

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

Of course.  It definitely compiles.  and runs without crashing. :)

I'll ignore your snippy tone and say that, yes eliminating warning is a good thing. However for this example, I know exactly where the two warnings are and that they are harmless in this case. In fact one of them even comes from a snippet I borrowed from the gtk api docs. If you are getting more warnings or errors, rather than say "did you even bother to compile this?" just tell us the specifics and of course how to correct them. In the meantime, heaven help you if you build downloaded projects on linux on a regular basis. Some makefiles even redirect the warnings to /dev/null since there are so many (obviously not a great thing).


Michael



________________________________________________________________________

#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;
}



_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list gnome org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list





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