Discussion from irc.gnome.org:#gtk+ Starting Aug 03 2004 12:07:54

<taf2>	hi, i have a little program threaded (shrug) but works in linux not in win32... In win32 it appears to deadlock on a call to gtk_widget_hide_all.  The app is initalized currently (works in linux) and the calling function first calls gdk_threads_enter before calling gtk_widget_hide_all.  Any ideas?
<mitch>	taf2: stop using gtk functions from more than one thread
<taf2>	mitch: why if i call gdk_threads_enter it should be safe right?
<mitch>	(if that's an option, otherwise you'll have to debug your locks)
<mitch>	taf2: i have no idea, what i said was just the standard disclaimer ;)
<taf2>	mitch: just wanted to know if anyone knows of any issues with calling gtk_widget_hide_all within a gdk_thread_enter/leave block
<mitch>	as i said, i have no idea :(
<mitch>	there is no general answer
<mitch>	when you use gtk threaded you have to control your threads' access to the widget hierarchy using you own locks
<taf2>	mitch: i thought you have to use g_threads_enter/leave to around gtk functions?
<taf2>	not a user defined lock
<mitch>	that is just to avoid concurrent use of gdk
<mitch>	it doesn't guarantee that GTK+ will do the right thing because it can't know what the right thing is
<taf2>	mitch: so a call to a gtk_widget_show_all/hide_all might cause some serious problems because there are parts of the widget not protected by gdk_threads_enter/leave right ?
<mitch>	no widget is protected by gdk_threads_*
<mitch>	that's why it's called gdk_, not gtk_
<taf2>	mitch: alright now i understand 
<mitch>	it's just the windowing system backends that's protected
<taf2>	alright i'll restructure things :-)
<mitch>	you can't simply use widgets (or GObjects in general) from different threads without ensuring yourself that all constraints are honored
<owen>	mitch: Well, that's not exactly how I'd describe it
<mitch>	that's why the general recommendation is to use gtk from *one* thread only
<owen>	mitch: Basically, there is one big lock that you hvae to get before performing any GTK+ or GDK operation
<mitch>	owen: well :)
<mitch>	taf2: better listen to owen ;)
<mitch>	owen: but hopefully my description was not totally bogus?
*	taf2 is a little confused awaiting some clarification :-)
<taf2>	mitch: it made sense to me
<owen>	mitch: well, there probably was some nugget of truth in it somewhere :-)
<taf2>	but before you explained it that way i understood it to be one global lock as own said
<mitch>	i think i was not totally wrong ;)
<owen>	taf2: Have you read the documentation on the subject?
<mitch>	owen: heh :)
<owen>	http://developer.gnome.org/doc/API/2.0/gdk/gdk-Threads.html
<taf2>	owen: yeah its been some time but i've used gtk with threads before 
<jpe>	taf2, the win32 backend may have additional threading issues in addition to the generic gtk/gdk ones
<taf2>	jpe: i think that's is what i'm experiencing because as i said in linux calling gtk_widget_hide_all within a gdk_threads_enter/leave block works fine
<owen>	taf2: Oh, win32, missed that. You can't use GTK+ in multiple threads on Win32
<jpe>	taf2, I'm not sure anyone has gone through the win32 api calls to see how they act in the presence of threads
<taf2>	ok, i'd like to start looking :)
<owen>	jpe: Well, the problems are pretty well known - the thing is that events are delivered to the thread that creates a toplevel on windows
<jpe>	taf2, also the windows procedure probably is called on the thread that create the window
<owen>	jpe: SO you basically need a worker thread that is responsible for creating all toplevels and receiving all events on behalf of the other threads to make GTK+ threading work on win32
<taf2>	owen: so what can be done to make this work in windows.  I'd like to devote some time to this 
<jpe>	the easiest thing to do is not use threads ;)
<owen>	taf2: See what I just said to jpe. It strikes me as maybe a week of work, but I'm not sure I've ever convinced Tor that its the right way to do things, so you should talk to him first.
<taf2>	jpe: i don't feel rushed ;)
<jpe>	owen, it's quite a bit of change -- it strikes me as a week of work for the initial version and then a few months finding the bugs
<jpe>	it will also have a performance impact
<taf2>	it seems that most of the work would be in gdkevents-win32.c right?
<owen>	jpe: I think it would actually make things a lot more straightforward and "more like X" than they are now. There's some ad-hoc hacks for expose handling during resizes, etc, that could be removed
<jpe>	I always thought that one of the reasons the initial Java versions seemed slow on win32 was the separate event thread
<owen>	jpe: But yeah, you might be chasing bugs for a while
<jpe>	The Java AWT, I mean
<owen>	jpe: The X model of an event queue where multiple events get read out of it asynchronously was designed to work well over a network / between processes. The overhead of implementing it in a thread shouldn't be significant
<jpe>	taf2, most of it is in gdkevents-win32.c but it will touch most things
<owen>	jpe: Of cours,e you'd get somewhat *different* updating behavior than other Win32 applications for resizes, etc, but I'm not sure we are doing that well there already
<jpe>	taf2, I would start by thinking of the event thread as a separate "server" thread that only communicated with other threads via an event queue
<jpe>	taf2, so to create a window a non-server thread would post a request for the server thread to create one
<jpe>	owen, I think it could work and be a real step forward (I'm all to aware of some of the current bugs)
<taf2>	jpe: perhaps using a g_async_queue would to pass messages
<jpe>	what might be somewhat tricky is drawing -- do you post requests to the server thread or do you do it directly after locking the window in some way
<owen>	jpe: I think you can just use the big GTK+ lock for that 
<owen>	jpe: That is, the server thread does gdk_threads_enter() gdk_threads_leave() before doing anything that might need locking with a different thread
<jpe>	taf2, I'm not completely familiar with the glib api, but some type of queue is probably the way to go.  My guess is that the server thread would be outside the mainloop, though
<owen>	taf2: I think GAsyncQueue + g_main_context_wakeup() should be suffiicient for what is needed for the event queue
<taf2>	jpe: i think a async queue is independent of the mainloop
<taf2>	alright i'm gonna give this a shot
<jpe>	owen, that might work to use the global lock.  What concerns me is a window being destroyed while being drawn on
<owen>	jpe: Does destruction have to go through the event thread? 
<owen>	jpe: I'm pretty sure it's all solveable in any case :-), though it might take some hard thinking
<jpe>	Can the usual windows TranslateMessage / DispatchMessage loop be used to drive the main loop of the server thread?
<owen>	jpe: I don't see why not, though you'd probably have to use SendMessage then to send widow creation events to the server thread?
<jpe>	owen, just checked MSDN and DestroyWindow must be called on the thread that created the window
<owen>	jpe: Well, doesn't really make things much more complex. GTK+ is already nicely set up for handling the fact that destruction actually happens at some later time. 
<jpe>	owen, I'd use SendMessage as a way to wake the server thread, but probably wouldn't pass the data itself through the windows message queue
<owen>	jpe: Hmm, using the global lock might not work though ... the problem is that gdk_window_new() needs to be synchronous
<owen>	jpe: but you dont' want to it to do a gdk_theads_leave()/enter(). 
<owen>	jpe: Though actually, window creation is fine - because no locking on a window until the ID is passed back out of the window thread
<jpe>	owen, how does gdk_window_new work on X11?
<owen>	jpe: It doesn't need to be synchronous on X11 - XIDs are assigned client side
<owen>	jpe: It's basically    "Create a window whose window ID will be 0x1234678. Show 0x12345678, Draw a line on 0x12345678...."
<jpe>	owen, we could use a XID in the client side that is different than the hwnd
<owen>	jpe: Only if we were passing drawing requests to the server thread. 
<owen>	jpe: Sounds over-engineered :-)
<jpe>	owen, I suspect we'll want a way for the server to do drawiung
<jpe>	owen, and then treat direct client thread drawing as an optimization
<owen>	jpe: See last comment.
<taf2>	owen|jpe: does this issue have an open bug report?
<owen>	taf2: http://bugzilla.gnome.org/show_bug.cgi?id=60620 I think
<jpe>	Not really, though there is a bug report about thread safety
<taf2>	should i open a new bug?
<taf2>	or add to  http://bugzilla.gnome.org/show_bug.cgi?id=60620
<jpe>	owen, but if you want to use the hwnd as the XID, you need to wait on the server thread to create the window
<owen>	taf2: Wouldn't hurt, but probably best to actually deal with this on list - post an initial design document to gtk-devel-list or whatever
<taf2>	owen: alright
<owen>	jpe: Yeah, that hurts a bit. Don't know how much it would affect overall performance ... creating windows isn't *that* common. 
<owen>	jpe: depends on how fast inter-thread IPC and context switches are on windows partly
<jpe>	owen, I agree, though I worry a bit that win32 will get hung up processing some message and not get around to creating it
<owen>	jpe: Shouldn't be worse than single-threaded though

Ending Aug 03 12:59:07
