That is some piece of work! :) I really have to thank you. I'll have a
look at it and I'll try it out ASAP. It would be great to have Gtk fully functional under Perl! Keep it up! Regards, -- David KubÃÄek System Specialist T-Systems PragoNet a.s. Mladà Boleslav, Na Karmeli 1457 Mobile: (420) 739 242 055 Phone: (420) 326 329 359 PGP: http://awk.cz/key.pgp http://awk.cz/key.pem Email: kubicek gedas cz david kubicek t-systems com kubicek awk cz Connection to localhost closed by remote host. Torsten Schoenfeld wrote: On Mon, 2008-03-24 at 14:47 +0100, David KubÃÄek wrote:I'm having problems with threads in my GTK application.All this should really just work. So I started looking into it. Tonight is now the fourth night in a row that I've been trying to fix this, and I still don't have a solution that works in every case. When you create a thread via threads->new, perl clones everythingïï (subs, variables)ï that is not marked as "shared" from the current thread. So normally, both threads see independent copies of all the variables and subs. It does this automatically for all the normal Perl stuff, but it can't do it for magic variables that are associated with underlying C objects. So perl provides a hook for these cases: when you define a CLONE method, it is called in the context of the new thread whenever one is created. Unfortunately, the CLONE method is called only with the package name and only once per package. So in order to clone our GObject wrappers, we need to keep a table of all the objects we ever encountered. Now the idea is that CLONE just increments the reference count of every object. When the thread exits, the cloned variables go out of scope and the references are released again. This is what the current thread-safety code in Glib::Object does. This works as long as there's a one-to-one mapping from C things to Perl variables. That's not the case for Glib::Object, though. When you have a signal handler for a button's clicked signal, the signal handler's first argument and the button variable from the outer scope are different Perl variables but they wrap the same C pointer. I think this is what breaks your demo programs: when the thread is created, both of those variables are cloned, but we only increment the reference count of the GObject once; when the thread exits, both variables go out of scope and the reference count is decremented twice. My idea of fixing this was to count the number of Perl wrappers we hand out for each GObject and in CLONE increment the reference count as many times as there are wrappers. This didn't seem to work properly: sometimes the programs still crashed, mostly there were leaks though. Another idea was to store a variable=>GObject mapping in the table I mentioned earlier and iterate this table in CLONE, referencing every GObject once. Since different variables might point to the same GObject, this amounts to increasing the reference count of some GObjects more than once. In retrospect, this should be exactly the same as the first approach -- but for some reason, this one worked a little better. A corresponding patch to Glib is attached. It's still not working correctly in every case, though. The attached program works fine for example, but if you enable the commented out inner thread stuff, it breaks. So, does anyone know how to get this going correctly? For reference, here's some useful information I found: â `perldoc perlmod' has a section about "Making your module threadsafe", mentioning CLONE and CLONE_SKIP. â `perldoc perlguts' has some general information about multiple threads and perl in "How multiple interpreters and concurrency are supported". ïâ <http://www.perlmonks.org/?node_id=483162> has a supposedly working Perl implementation of the CLONE stuff for inside-out objects. ïïâ In the thread <http://www.mail-archive.com/dev perl apache org/msg09877.html>, Stas Bekman talks about making mod_perl 2 thread-safe. He even created an example module demonstrating a supposedly working approach for an XS module that wraps the C objects. His C objects are only ever referenced by one variable, though. I have yet to try his approach of using a perl HV to store the mapping though. ïïïâ Once this all works on the Perl side, Andrew Cowie tells you to handle gtk+ itself when using multiple threads: <http://research.operationaldynamics.com/blogs/andrew/software/gnome-desktop/gtk-thread-awareness.html> |
Attachment:
signature.asc
Description: OpenPGP digital signature