GTK+ and threads question - "main" GTK+ lock.

2006-11-16 Thread Przemyslaw Tokarski

Hello list !

I'm in the process of coding a multithreaded GTK+ application. The 
application opens a window which contenst is being updated by a worker 
thread, however it is possible that the window does not exist anymore
(it received a "delete-event" signal) while the worker thread still tries 
to update it. To the window's "delete-event" signal a callback function 
is connected that sets some variable to NULL. Actually that variable is 
the window variable itself ('scan_status_window'). The code that does the 
update checks the value of that variable in the following manner:

-
gdk_threads_enter();
if ( scan_status_window == NULL ) {
  gdk_threads_leave();
  return;
}
.
.
.
/* Window update code runs here. */
.
.
.
gdk_flush();
gdk_threads_leave();
return;
-

My question is whether assuming that 'scan_status_window' is being set to
'NULL' in a callback function that is holding the "main" GTK+ lock
('gdk_threads_enter()' called right before 'gtk_main()') it is guaranteed
that when the window does not exist anymore 'scan_status_window' is set to
'NULL' ? Another words, whether update worker thread is unable to acquire the
lock until callback function returns and vice versa, window destruction won't
proceed until update worker thread releases the lock ? More precisely,
whether "delete-event" signal reception, delivery and callback function
execution operations are all executed within the "main" GTK+ lock (not just
the callback function itself) ? 

Best regards

Przemyslaw Tokarski
Lodz, Poland

PS. I'll summarize.
___
gtk-app-devel-list mailing list
gtk-app-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list


Re: GTK and threads

2006-02-07 Thread kornelix

Michael, thanks for your example. It works fine.

I had done almost the same thing (see code below), but my mistake was in 
trying to call the function below from event-response functions within 
main() as well as from threads. In the case of main(), which is  
completely enclosed within gdk_threads_enter() and gdk_threads_leave(), 
the nested call to gdk_threads_enter() results in a total lockup of the 
application. Some of my other (defective) variations caused a total 
lockup of the gnome desktop.


I am now trying to figure out my next approach:

1. Implement some kind of thread-specific global memory where I can save 
the GDK lock status of the thread and avoid the nested calls to 
gdk_threads_enter(). This seems impossible without modifying all 
functions to pass a thread-number argument or a pointer to the 
thread-specific memory.


2. Versions of my functions with and without the gdk_threads_enter() and 
_leave() calls (locking version calls non-locking version). Now I still 
have to figure out if being called from main() or a thread, or from 
another function that locks.


3. Do all GDK/GTK stuff within main() response functions, and deal with 
the application complexity of passing data back and forth between these 
functions and the thread functions. I am inclining to this because it is 
safe and sure.


QUESTION
I was hoping to find a way to send a text message to a window and have a 
corresponding response function, as for a menu selection or the 
"destroy" signal. I cannot find such a function, but surely this exists.


regards
Mike

=

//  print to a text view window ala printf()

void wprintf(GtkTextView *textWin, char *mess, ... )
{
  GtkTextBuffer  *textBuff;
  GtkTextItertextIter;
  GtkTextMark*textMark;

  va_list  arglist;
  char  message[200];

  va_start(arglist,mess);
  vsprintf(message,mess,arglist);
  va_end(arglist);

  gdk_threads_enter();

  textBuff = gtk_text_view_get_buffer(textWin);
  gtk_text_buffer_get_end_iter(textBuff,&textIter);
  gtk_text_buffer_insert(textBuff,&textIter,message,-1);
  gtk_text_buffer_get_end_iter(textBuff,&textIter);
  textMark = gtk_text_buffer_create_mark(textBuff,0,&textIter,0);
  gtk_text_view_scroll_to_mark(textWin,textMark,0,0,1,1);

  gdk_flush();// needed ??
  gdk_threads_leave();
}


Michael Torrie wrote:


kornelix wrote:


Thanks. I eagerly anticipate your example.



I have attached a sample file that uses threads in the way you 
described in your last post.  The gui consists of a single text 
display and a button.  When you click the button, a new thread is 
started that periodically (every second) sends a message to the text 
window.  When you close the window, the program will send a signal to 
each thread to terminal (well not a real signal, just sets a flag).  
Once all the threads have terminated, the program ends.  I have not 
implemented a proper signalling system to send signals to the threads 
nor have I used the pthread_join to properly rejoin threads that have 
quit.  Mainly because pthread_join blocks and that causes problems.


You'll notice the on_destroy callback has a loop that iterates the gtk 
event loop while we're waiting for the threads to stop.  This is 
because we're in a callback, already holding the gdk_thread_lock, so 
any waiting in here will prevent threads from aquiring their lock and 
thus finishing their loops.  So we iterate it.


The callbacks (including the pthread_create calls) already occur in 
the context of the main gdk lock, so no explicit locking is needed there.


See what you think.




I made a small code example like the one you described. It hung up. 
Then I figured out why: I am calling a function that has the 
gdk_threads_enter() and _leave() wrappers from main() as well as from 
a created thread. In the case of main(), the call to 
gdk_threads_enter() was a second call for that thread, and this is 
apparently fatal. I have to figure out how to detect and avoid this, 
or make multiple versions of the functions with and without the 
wrappers. If I call the function from the thread only, it works.




I really am not following what you are describing (please provide 
code) but it feels like you're definitely doing something wrong.  It 
needn't be this complicated from my experience.


One way of looking at the issue is that the FAQ example includes all 
main() code within the thread wrapper functions, meaning that any 
called functions better not have the wrappers. Would it be legitimate 
to treat main() like any other thread, and put the wrappers only 
around gtk/gdk calls? If I could do this, then functions would be 
usable from both main() and created threads.



Hmm.  Sounds complicated.  My gut feeling is that most of your 
difficulties are in not knowing when you are in the gdk lock already 
and when you need to initiate a lock.  Please tell me if my example 
code addresses any of the problems you have been having.  (and for

Re: GTK and threads

2006-02-06 Thread Michael Torrie

Boncek, John wrote:

How did you get an attachment to work with the list?  I have never known
that to work and often wished it would.


I simply attached it normally and sent it off!  Perhaps you have some 
attachment filtering on your mail server that you send through?   I 
don't know.


Michael






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


Re: GTK and threads

2006-02-06 Thread Michael Torrie

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 
#include 
#include 
#include 
#include 



#include  /* 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

Re: GTK and threads

2006-02-06 Thread Alan M. Evans
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 
> #include 
> #include 
> #include 
> #include 

#include  /* 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.gno

RE: GTK and threads

2006-02-06 Thread Boncek, John
How did you get an attachment to work with the list?  I have never known
that to work and often wished it would.

-Original Message-
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Michael Torrie
Sent: Monday, February 06, 2006 1:22 PM
To: kornelix
Cc: gtk app dev mail list
Subject: Re: GTK and threads

kornelix wrote:
> Thanks. I eagerly anticipate your example.

I have attached a sample file that uses threads in the way you described 
in your last post.  The gui consists of a single text display and a 
button.  When you click the button, a new thread is started that 
periodically (every second) sends a message to the text window.  When 
you close the window, the program will send a signal to each thread to 
terminal (well not a real signal, just sets a flag).  Once all the 
threads have terminated, the program ends.  I have not implemented a 
proper signalling system to send signals to the threads nor have I used 
the pthread_join to properly rejoin threads that have quit.  Mainly 
because pthread_join blocks and that causes problems.

You'll notice the on_destroy callback has a loop that iterates the gtk 
event loop while we're waiting for the threads to stop.  This is because 
we're in a callback, already holding the gdk_thread_lock, so any waiting 
in here will prevent threads from aquiring their lock and thus finishing 
their loops.  So we iterate it.

The callbacks (including the pthread_create calls) already occur in the 
context of the main gdk lock, so no explicit locking is needed there.

See what you think.


> 
> I made a small code example like the one you described. It hung up. Then

> I figured out why: I am calling a function that has the 
> gdk_threads_enter() and _leave() wrappers from main() as well as from a 
> created thread. In the case of main(), the call to gdk_threads_enter() 
> was a second call for that thread, and this is apparently fatal. I have 
> to figure out how to detect and avoid this, or make multiple versions of

> the functions with and without the wrappers. If I call the function from

> the thread only, it works.
> 

I really am not following what you are describing (please provide code) 
but it feels like you're definitely doing something wrong.  It needn't 
be this complicated from my experience.

> One way of looking at the issue is that the FAQ example includes all 
> main() code within the thread wrapper functions, meaning that any called

> functions better not have the wrappers. Would it be legitimate to treat 
> main() like any other thread, and put the wrappers only around gtk/gdk 
> calls? If I could do this, then functions would be usable from both 
> main() and created threads.

Hmm.  Sounds complicated.  My gut feeling is that most of your 
difficulties are in not knowing when you are in the gdk lock already and 
when you need to initiate a lock.  Please tell me if my example code 
addresses any of the problems you have been having.  (and for the real 
GTK experts out there, feel free to point out where I'm doing everything 
wrong.)

Michael


> 
> It will not take long, so I will just try this.
> 
> regards
> 
> 
> 
___
gtk-app-devel-list mailing list
gtk-app-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list


Re: GTK and threads

2006-02-06 Thread Michael Torrie

kornelix wrote:

Thanks. I eagerly anticipate your example.


I have attached a sample file that uses threads in the way you described 
in your last post.  The gui consists of a single text display and a 
button.  When you click the button, a new thread is started that 
periodically (every second) sends a message to the text window.  When 
you close the window, the program will send a signal to each thread to 
terminal (well not a real signal, just sets a flag).  Once all the 
threads have terminated, the program ends.  I have not implemented a 
proper signalling system to send signals to the threads nor have I used 
the pthread_join to properly rejoin threads that have quit.  Mainly 
because pthread_join blocks and that causes problems.


You'll notice the on_destroy callback has a loop that iterates the gtk 
event loop while we're waiting for the threads to stop.  This is because 
we're in a callback, already holding the gdk_thread_lock, so any waiting 
in here will prevent threads from aquiring their lock and thus finishing 
their loops.  So we iterate it.


The callbacks (including the pthread_create calls) already occur in the 
context of the main gdk lock, so no explicit locking is needed there.


See what you think.




I made a small code example like the one you described. It hung up. Then 
I figured out why: I am calling a function that has the 
gdk_threads_enter() and _leave() wrappers from main() as well as from a 
created thread. In the case of main(), the call to gdk_threads_enter() 
was a second call for that thread, and this is apparently fatal. I have 
to figure out how to detect and avoid this, or make multiple versions of 
the functions with and without the wrappers. If I call the function from 
the thread only, it works.




I really am not following what you are describing (please provide code) 
but it feels like you're definitely doing something wrong.  It needn't 
be this complicated from my experience.


One way of looking at the issue is that the FAQ example includes all 
main() code within the thread wrapper functions, meaning that any called 
functions better not have the wrappers. Would it be legitimate to treat 
main() like any other thread, and put the wrappers only around gtk/gdk 
calls? If I could do this, then functions would be usable from both 
main() and created threads.


Hmm.  Sounds complicated.  My gut feeling is that most of your 
difficulties are in not knowing when you are in the gdk lock already and 
when you need to initiate a lock.  Please tell me if my example code 
addresses any of the problems you have been having.  (and for the real 
GTK experts out there, feel free to point out where I'm doing everything 
wrong.)


Michael




It will not take long, so I will just try this.

regards



#include 
#include 
#include 
#include 
#include 

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) {
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);
}

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);

   

Re: GTK and threads

2006-02-06 Thread kornelix
This FAQ entry is where I started from. My first attempt at making 
threads work resulted in all threads running one after the other, in 
series instead of in parallel, because I was locking the whole thread 
with gdk_threads_enter() at the beginning. I "progressed" to trying to 
lock only the gtk/gdk calls in order to restore the parallelism. I am 
still trying to make it work, but creating bugs like the one I described 
earlier (two calls to gdk_threads_enter() in the same thread results in 
lockup).


regards


There's a FAQ entry about this:
http://www.gtk.org/faq/#AEN482
And I'm pretty sure there's something very similar in the API
documentation, but I don't feel like digging for it now.

 


Bill Gates can rest quietly at night. The threat from Linux
is only in the imagination of the Linux geeks.
   



 


Please do not get angry. Shooting the messange is not the answer.
   



I find it ironic that you say something so obviously inflammatory (and
in this particular case, based on your incorrect assumptions), and then
tell us not to get angry.  If you don't want to get shot, then don't
lace your message with thinly-veiled insults and accusations.

-brian

-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFD5xdX6XyW6VEeAnsRAmEKAJ9SSSNmiki90556Um3bCusQ8BX83wCgulr5
9J/8Ggqq5GV8hsdD8C5CLQE=
=LZO0
-END PGP SIGNATURE-
___
gtk-app-devel-list mailing list
gtk-app-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

 


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


Re: GTK and threads

2006-02-06 Thread kornelix

OK, I see. That was illuminating, but not the whole story.

In Win32, you can send messages to a window to make it update from its 
paint() function in its owning thread, or you can write directly to it 
from another thread, if you have its handle. I went and found an old 
code fragment from a graphic application I wrote about 1995:

SelectObject(hDC,hColorBrush[ii]); // draw in color
PatBlt(hDC,ipx,ipy,xw,yw,PATCOPY);
hDC is a handle to a "device context", basically a window pointer. The 
above code runs in a thread that did not create the window. No explicit 
locks are evident. The point here was speed: screen updates were much 
faster this way compared to waiting for the paint() function to run 
after invalidating a portion of the window.


My memory of win32 is old but I think the above is correct. I am sure 
your points are also correct.


regards



Tor Lillqvist wrote:


kornelix writes:
> I hope you will indulge me. I don't recall any counterparts in
> Win32 to these wrapper functions (gtk/gdk init / enter / leave).
> Perhaps I am off base, but I think Win32 takes care of its own
> locking and threading business.

Well, surprise, as far as I know, it doesn't. For instance an utterly
trivial-looking Win32 API like SetWindowText() doesn't directly
manipulate the window's title. It sends a message to the thread that
owns (created) the window in question. If the window was created from
another thread, that doesn't have a message pump (isn't waiting to
handle Windows messages most of the time), but for instance is another
random "worker" thread that you just happened to create a window from,
you will have fun.

You don't need to google for long to find articles with statements
like:

   You get the assertions because MFC does not permit you to access
   most CWnd functions from a thread that did not create the window.
   The assertions are a warning that you are attempting an unsafe
   operation because the MFC message routing code is not thread safe.

And that is just an example, written by somebody who says he is a VC++
MVP, so presumably knows what he is talking about.

The article quoted above is from 2002, so of course, it might be that
I am completely wrong here, and that some very new MFC version
actually is all-singing all-dancing multi-thread-transparent where
user code can do anything it wants from any thread, like you say. On
the other hand, that doesn't seem likely, as MFC is much on its way
out, isn't it, considering the intended future with managed code,
Windows.Forms and whatnot?

> One of you mentioned that X11 has no thread awareness in its user 
> (caller) protocol. Sounds great to me. Was this a criticism?


No, on the contrary. I mentioned it as a comparison to the Win32
windowing and graphics API, which isn't based on a network protocol,
and where thread dependencies are very much built-in (which makes it
much harder for a toolkit running on top of it to support
multi-threadedness).

> Sadly this is the typical state of documentation for Linux and most 
> open-source software.


If you feel like that, it's great opportunity for you to help, isn't it?

--tml

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

 


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


Re: GTK and threads

2006-02-06 Thread kornelix

Thanks. I eagerly anticipate your example.

I made a small code example like the one you described. It hung up. Then 
I figured out why: I am calling a function that has the 
gdk_threads_enter() and _leave() wrappers from main() as well as from a 
created thread. In the case of main(), the call to gdk_threads_enter() 
was a second call for that thread, and this is apparently fatal. I have 
to figure out how to detect and avoid this, or make multiple versions of 
the functions with and without the wrappers. If I call the function from 
the thread only, it works.


One way of looking at the issue is that the FAQ example includes all 
main() code within the thread wrapper functions, meaning that any called 
functions better not have the wrappers. Would it be legitimate to treat 
main() like any other thread, and put the wrappers only around gtk/gdk 
calls? If I could do this, then functions would be usable from both 
main() and created threads.


It will not take long, so I will just try this.

regards


Michael Torrie wrote:


kornelix wrote:

Thanks to the three of you for your help and information. I will 
continue trying to make GTK work for my threaded application, and 
post progress (or lack thereof).


I am still confused (by apparently conflicting inputs from the GTK 
FAQ and yourselves) about when I must use which wrapper calls to 
force the GDK/GTK functions to single-thread themselves. First, is 
there a distinction between the main() thread and threads created 
later with pthread_create(), or should I be following the same rules? 
I have been making a distinction, and I am thinking this must be wrong.




Posting some code is a good start.  I think that the only way to get 
this solved is to have a complete working (or non-working), compilable 
source code snippet that illustrates very simply what you are trying 
to do.  Then we can identify the problems.  I myself am not 
experienced enough to deduce the problems solely from the code 
snippets you have below.


To this end later today I will build a very small C program that I 
believe will illustrate what you are trying to accomplish.  I will 
have a simple button that, upon clicking, will spawn a thread that 
will just do something simple, like writing text to the window or 
something.


Yes the documentation for GTK is lacking in some areas (like the 
proper ways to do threading and things).  However there are many, many 
good source code examples out there of projects large and small that 
do work.


Anyway, I will post my example code and findings later today.

Michael




The rules as I understand them now:

Main program:
   g_thread_init(NULL);
   gdk_threads_init();
   gtk_init(&argc, &argv);
 ...
   gdk_threads_enter();  //  I had omitted this step
   win = gtk_window_new(...);
   ... add some menus to win
   gtk_widget_show_all(win);
   gtk_main();  gdk_threads_leave();

menu event function:
   pthread_create() a response thread

menu response thread: every GTK/GDK function wrapped as follows:
   gdk_threads_enter();
   ... do GTK calls to create / update windows and / or get user 
input

   gdk_flush();
   gdk_threads_leave();

Signal response functions: always in main() thread, without 
enter/leave wrapper calls.


Some Glib functions (e.g. idle, timeout): always in main() thread, 
with enter/leave wrappers.

(I am not using these, so I can live with the ambiguity for now).

Now I am going to harangue you once again about the need for all the 
above stuff. I hope you will indulge me. I don't recall any 
counterparts in Win32 to these wrapper functions (gtk/gdk init / 
enter / leave). Perhaps I am off base, but I think Win32 takes care 
of its own locking and threading business. I still think GTK should 
do the same. The GTK user (caller) should not have to single-thread 
the functions by putting wrappers around the calls. The above rules 
are simply awful. If GTK must single-thread (some of) its function 
calls, it should manage this itself.


I have been advised several times to move all GTK calls into the 
main() thread and keep them out of the created threads. I hope this 
is not the answer, because this makes the application much more 
complex. For a simple example: I want to write text to a logging 
window from multiple threads. I wrote a simple function to do this 
that works like printf(). To avoid GTK calls from the threads, I 
would have to create a queue of such messages and have an idle 
function in main() that checks the queue and updates the window, or 
(better), have the thread functions send a message to the logging 
window and have its event function take care of the updates. For more 
complex cases, e.g. graphic updates or user dialogs, it just gets 
messier. Am I failing to understand something here?


One of you mentioned that X11 has no thread awareness in its user 
(caller) protocol. Sounds great to me. Was this a criticism?


The lockup problem I mentioned was definitely GTK. It w

Re: GTK and threads

2006-02-06 Thread Michael Torrie

kornelix wrote:
Thanks to the three of you for your help and information. I will 
continue trying to make GTK work for my threaded application, and post 
progress (or lack thereof).


I am still confused (by apparently conflicting inputs from the GTK FAQ 
and yourselves) about when I must use which wrapper calls to force the 
GDK/GTK functions to single-thread themselves. First, is there a 
distinction between the main() thread and threads created later with 
pthread_create(), or should I be following the same rules? I have been 
making a distinction, and I am thinking this must be wrong.



Posting some code is a good start.  I think that the only way to get 
this solved is to have a complete working (or non-working), compilable 
source code snippet that illustrates very simply what you are trying to 
do.  Then we can identify the problems.  I myself am not experienced 
enough to deduce the problems solely from the code snippets you have below.


To this end later today I will build a very small C program that I 
believe will illustrate what you are trying to accomplish.  I will have 
a simple button that, upon clicking, will spawn a thread that will just 
do something simple, like writing text to the window or something.


Yes the documentation for GTK is lacking in some areas (like the proper 
ways to do threading and things).  However there are many, many good 
source code examples out there of projects large and small that do work.


Anyway, I will post my example code and findings later today.

Michael




The rules as I understand them now:

Main program:
   g_thread_init(NULL);
   gdk_threads_init();
   gtk_init(&argc, &argv);
 ...
   gdk_threads_enter();  //  I had omitted this step
   win = gtk_window_new(...);
   ... add some menus to win
   gtk_widget_show_all(win);
   gtk_main();  gdk_threads_leave();

menu event function:
   pthread_create() a response thread

menu response thread: every GTK/GDK function wrapped as follows:
   gdk_threads_enter();
   ... do GTK calls to create / update windows and / or get user input
   gdk_flush();
   gdk_threads_leave();

Signal response functions: always in main() thread, without enter/leave 
wrapper calls.


Some Glib functions (e.g. idle, timeout): always in main() thread, with 
enter/leave wrappers.

(I am not using these, so I can live with the ambiguity for now).

Now I am going to harangue you once again about the need for all the 
above stuff. I hope you will indulge me. I don't recall any counterparts 
in Win32 to these wrapper functions (gtk/gdk init / enter / leave). 
Perhaps I am off base, but I think Win32 takes care of its own locking 
and threading business. I still think GTK should do the same. The GTK 
user (caller) should not have to single-thread the functions by putting 
wrappers around the calls. The above rules are simply awful. If GTK must 
single-thread (some of) its function calls, it should manage this itself.


I have been advised several times to move all GTK calls into the main() 
thread and keep them out of the created threads. I hope this is not the 
answer, because this makes the application much more complex. For a 
simple example: I want to write text to a logging window from multiple 
threads. I wrote a simple function to do this that works like printf(). 
To avoid GTK calls from the threads, I would have to create a queue of 
such messages and have an idle function in main() that checks the queue 
and updates the window, or (better), have the thread functions send a 
message to the logging window and have its event function take care of 
the updates. For more complex cases, e.g. graphic updates or user 
dialogs, it just gets messier. Am I failing to understand something here?


One of you mentioned that X11 has no thread awareness in its user 
(caller) protocol. Sounds great to me. Was this a criticism?


The lockup problem I mentioned was definitely GTK. It was repeatable: I 
started my (faulty) GTK app, selected a menu causing a thread creation 
with GTK calls, and the whole GNOME desktop froze up. Nothing worked at 
all, not even a terminal launch from the panel. I had to power off. 
IIRC, it was the situation depicted above with the missing call to 
gtk_threads_enter().


<<
You're looking at this in an overly-complicated way. Here are a few 
guidelines, all of which probably have appropriate documentation 
somewhere: ...

 >>
Sadly this is the typical state of documentation for Linux and most 
open-source software. The insider gurus and macho-geeks don't need the 
documentation, therefore it does not exist, is outdated, is scattered 
and disorganized, or just wrong. When web forums and e-mail lists are 
the only support you get, then quality documentation is of the utmost 
importance. Bill Gates can rest quietly at night. The threat from Linux 
is only in the imagination of the Linux geeks.


Please do not get angry. Shooting the messange is not the answer. I am 
an old Windows progra

Re: GTK and threads

2006-02-06 Thread Tor Lillqvist
kornelix writes:
 > I hope you will indulge me. I don't recall any counterparts in
 > Win32 to these wrapper functions (gtk/gdk init / enter / leave).
 > Perhaps I am off base, but I think Win32 takes care of its own
 > locking and threading business.

Well, surprise, as far as I know, it doesn't. For instance an utterly
trivial-looking Win32 API like SetWindowText() doesn't directly
manipulate the window's title. It sends a message to the thread that
owns (created) the window in question. If the window was created from
another thread, that doesn't have a message pump (isn't waiting to
handle Windows messages most of the time), but for instance is another
random "worker" thread that you just happened to create a window from,
you will have fun.

You don't need to google for long to find articles with statements
like:

You get the assertions because MFC does not permit you to access
most CWnd functions from a thread that did not create the window.
The assertions are a warning that you are attempting an unsafe
operation because the MFC message routing code is not thread safe.

And that is just an example, written by somebody who says he is a VC++
MVP, so presumably knows what he is talking about.

The article quoted above is from 2002, so of course, it might be that
I am completely wrong here, and that some very new MFC version
actually is all-singing all-dancing multi-thread-transparent where
user code can do anything it wants from any thread, like you say. On
the other hand, that doesn't seem likely, as MFC is much on its way
out, isn't it, considering the intended future with managed code,
Windows.Forms and whatnot?

 > One of you mentioned that X11 has no thread awareness in its user 
 > (caller) protocol. Sounds great to me. Was this a criticism?

No, on the contrary. I mentioned it as a comparison to the Win32
windowing and graphics API, which isn't based on a network protocol,
and where thread dependencies are very much built-in (which makes it
much harder for a toolkit running on top of it to support
multi-threadedness).

 > Sadly this is the typical state of documentation for Linux and most 
 > open-source software.

If you feel like that, it's great opportunity for you to help, isn't it?

--tml

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


Re: GTK and threads

2006-02-06 Thread Brian J. Tarricone
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

kornelix wrote:

> Brian J. Tarricone wrote:
>
>> You're looking at this in an overly-complicated way. Here are a few
>> guidelines, all of which probably have appropriate documentation
>> somewhere: ...
>
> Sadly this is the typical state of documentation for Linux and most
> open-source software. The insider gurus and macho-geeks don't need the
> documentation, therefore it does not exist, is outdated, is scattered
> and disorganized, or just wrong. When web forums and e-mail lists are
> the only support you get, then quality documentation is of the utmost
> importance.

There's a FAQ entry about this:
http://www.gtk.org/faq/#AEN482
And I'm pretty sure there's something very similar in the API
documentation, but I don't feel like digging for it now.

> Bill Gates can rest quietly at night. The threat from Linux
> is only in the imagination of the Linux geeks.

> Please do not get angry. Shooting the messange is not the answer.

I find it ironic that you say something so obviously inflammatory (and
in this particular case, based on your incorrect assumptions), and then
tell us not to get angry.  If you don't want to get shot, then don't
lace your message with thinly-veiled insults and accusations.

-brian

-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFD5xdX6XyW6VEeAnsRAmEKAJ9SSSNmiki90556Um3bCusQ8BX83wCgulr5
9J/8Ggqq5GV8hsdD8C5CLQE=
=LZO0
-END PGP SIGNATURE-
___
gtk-app-devel-list mailing list
gtk-app-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list


GTK and threads

2006-02-05 Thread kornelix
Thanks to the three of you for your help and information. I will 
continue trying to make GTK work for my threaded application, and post 
progress (or lack thereof).


I am still confused (by apparently conflicting inputs from the GTK FAQ 
and yourselves) about when I must use which wrapper calls to force the 
GDK/GTK functions to single-thread themselves. First, is there a 
distinction between the main() thread and threads created later with 
pthread_create(), or should I be following the same rules? I have been 
making a distinction, and I am thinking this must be wrong.


The rules as I understand them now:

Main program:
   g_thread_init(NULL);
   gdk_threads_init();
   gtk_init(&argc, &argv);
 ...
   gdk_threads_enter();  //  I had omitted this step
   win = gtk_window_new(...);
   ... add some menus to win
   gtk_widget_show_all(win);
   gtk_main();   
   gdk_threads_leave();


menu event function:
   pthread_create() a response thread

menu response thread: every GTK/GDK function wrapped as follows:
   gdk_threads_enter();
   ... do GTK calls to create / update windows and / or get user input
   gdk_flush();
   gdk_threads_leave();

Signal response functions: always in main() thread, without enter/leave 
wrapper calls.


Some Glib functions (e.g. idle, timeout): always in main() thread, with 
enter/leave wrappers.

(I am not using these, so I can live with the ambiguity for now).

Now I am going to harangue you once again about the need for all the 
above stuff. I hope you will indulge me. I don't recall any counterparts 
in Win32 to these wrapper functions (gtk/gdk init / enter / leave). 
Perhaps I am off base, but I think Win32 takes care of its own locking 
and threading business. I still think GTK should do the same. The GTK 
user (caller) should not have to single-thread the functions by putting 
wrappers around the calls. The above rules are simply awful. If GTK must 
single-thread (some of) its function calls, it should manage this itself.


I have been advised several times to move all GTK calls into the main() 
thread and keep them out of the created threads. I hope this is not the 
answer, because this makes the application much more complex. For a 
simple example: I want to write text to a logging window from multiple 
threads. I wrote a simple function to do this that works like printf(). 
To avoid GTK calls from the threads, I would have to create a queue of 
such messages and have an idle function in main() that checks the queue 
and updates the window, or (better), have the thread functions send a 
message to the logging window and have its event function take care of 
the updates. For more complex cases, e.g. graphic updates or user 
dialogs, it just gets messier. Am I failing to understand something here?


One of you mentioned that X11 has no thread awareness in its user 
(caller) protocol. Sounds great to me. Was this a criticism?


The lockup problem I mentioned was definitely GTK. It was repeatable: I 
started my (faulty) GTK app, selected a menu causing a thread creation 
with GTK calls, and the whole GNOME desktop froze up. Nothing worked at 
all, not even a terminal launch from the panel. I had to power off. 
IIRC, it was the situation depicted above with the missing call to 
gtk_threads_enter().


<<
You're looking at this in an overly-complicated way. Here are a few 
guidelines, all of which probably have appropriate documentation 
somewhere: ...

>>
Sadly this is the typical state of documentation for Linux and most 
open-source software. The insider gurus and macho-geeks don't need the 
documentation, therefore it does not exist, is outdated, is scattered 
and disorganized, or just wrong. When web forums and e-mail lists are 
the only support you get, then quality documentation is of the utmost 
importance. Bill Gates can rest quietly at night. The threat from Linux 
is only in the imagination of the Linux geeks.


Please do not get angry. Shooting the messange is not the answer. I am 
an old Windows programmer trying to change his spots. I am no Microsoft 
fan, and I hope you Linux / open-source geeks can put some brakes on the 
bullying monopoly. I am fairly geeky myself, but still an infant in the 
Linux arena, and very grateful for all the help I can get.


regards


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