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

Reply via email to