help with threads




I am trying to get menus working in threaded gtk program.
This is a simple test program that alternates label text from a
created thread,  with a checkbox to start & stop the thread.

If i take out g_thread_init, then the menu will work, but the checkbox
and label will not.  If i put g_thread_init in, then the opposite: menu
will lock up the application, but checkbox & label are ok.

I need somebody to massage my puny little brain on this one.

/********* start **********/
#include <gtk/gtk.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>

gboolean RUN = FALSE;
pthread_t	thread;
GtkWidget	*label;
gchar *textA = "label";
gchar *textB = "LABEL";

void *process(void *arg) {
	char *string = malloc(sizeof(char)*10);
	char **str = &string;
	g_print("thread starting:");
	while(RUN) {
		gdk_threads_enter();
		gtk_label_get(GTK_LABEL(label), str);
		if (!strcmp(*str, textB))	//if label set to textB
			gtk_label_set_text(GTK_LABEL(label), textA);
		else
			gtk_label_set_text(GTK_LABEL(label), textB);
		gdk_threads_leave();
		g_print(".");
		usleep(100000);
	}
	g_print(" thread returning\n");
	return NULL;
}

void start_stop(GtkWidget *widget, gpointer data) {
	int ret;
	void *process_return;
	if (GTK_TOGGLE_BUTTON(widget)->active) {	//start
		RUN = TRUE;
		ret = pthread_create(&thread, NULL, process, (void *)"run");
		if (ret != 0) g_printerr("thread creation failed: %d\n", ret);
	} else {									//stop
		RUN = FALSE;
		ret = pthread_join(thread, &process_return);
		if (ret != 0) g_printerr("thread join failed: %d\n", ret);
	}
}

gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) {
	return(FALSE);	//we want main window to be destroyed
}

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

void helloCallback(GtkWidget *widget, gpointer data) {
	g_print("hello\n");
}

int main(int argc, char *argv[]) {
	GtkWidget *window;
	GtkWidget *button;
	GtkWidget *hbox;

	/* menu */
	GtkWidget *menuBar;
	GtkWidget *menu;
	GtkWidget *menuItem;
	GtkWidget *root_menu;
	/* end menu */

	g_thread_init(NULL);
	if (!g_thread_supported()) {
		g_printerr("glib threads not supported\n");
		exit(-1);
	}
	gtk_init(&argc, &argv);
/*	if (!gdk_threads_mutex) {
		g_printerr("gdk threads not supported\n");
		exit(-1);
	}	*/
	button = gtk_check_button_new_with_label("run");
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
	gtk_signal_connect(GTK_OBJECT(button), "toggled", 
		GTK_SIGNAL_FUNC(start_stop), NULL);
	gtk_widget_show(button);

	label = gtk_label_new("label");
	gtk_widget_show(label);
	
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_container_border_width(GTK_CONTAINER(window), 10);
	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);
	gtk_widget_show(window);

	hbox = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, FALSE, 5);
	gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 5);

	/* menu */
	menu = gtk_menu_new();	//holds menu items
	menuItem = gtk_menu_item_new_with_label("hello");
	gtk_menu_append(GTK_MENU(menu), menuItem);
	gtk_signal_connect(GTK_OBJECT(menuItem), "activate",
		GTK_SIGNAL_FUNC(helloCallback), NULL);
	gtk_widget_show(menuItem);
	root_menu = gtk_menu_item_new_with_label("Root Menu");
	gtk_widget_show(root_menu);
    gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu);
	//
	menuBar = gtk_menu_bar_new();
	gtk_box_pack_end(GTK_BOX(hbox), menuBar, FALSE, FALSE, 5);
	gtk_widget_show(menuBar);
    gtk_menu_bar_append (GTK_MENU_BAR (menuBar), root_menu);
	/* end menu */

	gtk_widget_show(hbox);
	gtk_container_add(GTK_CONTAINER(window), hbox);

//	gdk_threads_enter();
	gtk_main();
//	gdk_threads_leave();
	return(0);
}
/********* EOF **********/



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