On Mon, 2009-11-23 at 11:01 +0000, Simon Marlow wrote: > Axel, this is great news, many thanks for working on it! > > I'm interested in using Cairo from multiple threads. What exactly is > supported there? Can I run an arbitrary Render operation on any thread > I like?
Yes, as long as you manipulate each Cairo object within one thread: http://lists.cairographics.org/archives/cairo/2009-February/016648.html However, it involves some effort to repaint a widget using a different thread even through you never directly paint to the screen due to Gtk's double buffering. The reason is that the expose event EExpose internally sets a Pixmap aside before the signal is emitted and will copy this Pixmap to the actual window once the signal handler has returned. Thus, you cannot spawn a thread off in the EExpose handler since it would have to finish before the handler can return. So I think you need to pro-actively update a Pixmap using Cairo whenever the content should changes. You do this in its own thread using renderWithDrawable. Whenever the the new Pixmap is ready, you call windowInvalidateRectangle on the DrawWindow of the DrawingArea. This will trigger the expose handler. In the expose handler of the DrawingArea, you retrieve the Pixmap from the worker thread and you copy it to the screen using Drawable.drawDrawable. You should probably turn off double buffering using widgetSetDoubleBuffered since this just means the pixmap is copied twice. In order to avoid that you show half-ready images, your worker thread could keep two Pixmaps: one for drawing, the other one containing the last complete image. I've never tried this, but this is how I understand the documentation. Cheers, Axel. > Cheers, > Simon > > On 22/11/09 19:58, Axel Simon wrote: > > Dear Simon, Duncan, > > > > -threaded now works with Gtk2Hs. See below. > > > > > > On Tue, 2009-11-10 at 14:14 +0000, Simon Marlow wrote: > >> On 10/11/2009 13:52, Axel Simon wrote: > > > >>>> Does the traceback in my original message give you enough information? > >>>> (reproduced at the end of this message) > >>> > >>> Well, you omitted 'various' stuff. I agree that something is calling > >>> back into C when it shouldn't. Are there any function names between > >>> frame 6 and 44 that would give me a clue where we've been negligent? > >> > >> Ah yes, sorry. Here's the full trace: > >> > >> (gdb) where > >> #0 0x0000003c0aa0af19 in pthread_cond_wait@@GLIBC_2.3.2 () from > >> /lib64/libpthread.so.0 > >> #1 0x00000000005ac6e9 in waitCondition () > >> #2 0x00000000005c67ab in waitForReturnCapability () > >> #3 0x00000000005a3f17 in rts_lock () > >> #4 0x00000000004ce397 in SystemziGlibziGObject_d1wV () > >> #5 0x0000003c10cd8eed in ?? () from /usr/lib64/libgtk-x11-2.0.so.0 > >> #6 0x0000003c0ba0d6a8 in g_object_unref () from /lib64/libgobject-2.0.so.0 > >> #7 0x0000003c10ccebc7 in gtk_tree_view_remove_column () from > > > > I understand now where this error is. There is a call in your program to > > cellLayoutSetAttributes. This function installs certain callbacks that > > Gtk+ tries to free in the stack trace above. The call stack above is > > triggered by > > > >> #41 0x0000003c0ba0d632 in g_object_unref () > > from /lib64/libgobject-2.0.so.0 > >> #42 0x00000000005abdfd in runAllCFinalizers () > > > > ... and I suppose runAllCFinalizers is the GC and an 'unsafe' call from > > Haskell. Thus, it is actually only possible to use the C function > > freeHaskellPtr. I do that now. > > > > > >> (3) use Haskell finalizers with idleAdd as a temporary workaround. > >> > >> (3) is by far the easiest solution, but it may have unacceptable > >> performance, I'd interested to know if that's the case. The runtime > >> does batch multiple finalizers so they don't each get a separate Haskell > >> thread, so it might not be too bad. > >> > >> I'm not completely averse to doing (1) if it's absolutely necessary, but > >> I'd like to do something that avoids having a dependency on a future > >> version of GHC. And all things being equal, we should avoid adding new > >> features to GHC because they're hard to remove again. > > > > So now there are two kinds of finalizers: > > > > (1) those that directly free the C GObject which are used in Cairo and > > (in the future) Pango, Pixbuf, and all other libraries whose objects do > > not call back into Haskell. > > > > (2) all finalizers of Gtk+ and libraries that build upon Gtk+ > > (sourceview, etc). These call a special finalizer that enqueues the > > object to be finalized into an array and install a an g_idle_add handler > > that will run the finalizers from the main iteration loop of Gtk+ and, > > thus, from the right thread and from a safe call. > > > > All objects in (2) can therefore call back to Haskell while they are > > being destroyed. I have therefore moved the possibility to add a WeakRef > > (a function that is called when a GObject is finalized) to from GObject > > to Graphics.UI.Gtk.Abstract.Object which means they can only be > > installed on objects that fall into category (2). > > > > So the darcs version of Gtk2Hs with -threaded should now work as > > expected. You're still responsible to call Gtk2Hs function from the same > > Haskell thread. But you can create Cairo drawings and Pagno stuff in > > different threads and pass them to the main thread. > > > > Cheers, > > Axel. > > > > ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Gtk2hs-devel mailing list Gtk2hs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/gtk2hs-devel