Integrating ghc's rts into other single-threaded frameworks

All, I'm thinking about how to make threaded Haskell program work nicely with Gtk+ (the widget toolkit) and whether the new threaded rts will help or not. Graphics toolkits (X windows or win32 GDI) typically have pretty strict requirements on threads. While it is possible to make use of multiple OS/kernel threads, the locking issues are non-trivial and it is generally not encouraged. It is probably best to consider them as single threaded libraries. So while my initial thought was to make a blocking call to Gtk's main loop in another OS thread using the threadsafe atribute so that it runs in a separate thread, I now think this is not the best approach. The problem is that calls to Gtk functions in other Haskell threads will be made in a different OS thread from the one running the Gtk main loop. Would bound threads help? I'm not sure I understand the idea very well. (It is possible to set up a polling system where gtk periodically calls back to Haskell land and we call ghc's yield function. As you might expect, this works but performs poorly and consumes cpu time when idle.) So a better approach might be to try and integrate the main loops of gtk+ and the ghc rts. Gtk provides a fairly flexible API for controlling it's main loop. You can either run it as a single blocking function or run a single iteration at a time or even split up each iteration into phases. So the question is which main loop gets to block? Unfortunately, neither can do so unless it knows the full set of file descriptors and timeouts of both main loops. So the question is which would be easier? The glib main loop could act as the master main loop since there are functions for registering callbacks for fds and timeouts. At the moment, I don't believe there is any way to ask the ghc rts what fds & timeouts it is interested in. The glib main loop is designed so that it can integrate into an external main loop (though no doubt with some difficulty). See: http://www.gtk.org/~otaylor/gtk/2.0/main-loop.html also an older message http://mail.gnome.org/archives/gtk-devel-list/1999-March/msg00145.html The glib main loop can be split up into phases (prepare, query, check, dispatch), see: http://developer.gnome.org/doc/API/2.0/glib/glib-The-Main-Event-Loop.html#ma... It's not clear to me how one would use that to integrate two main loops, but perhaps it's clearer to the ghc rts gurus. There is also a function for changing the 'poll' function that the glib main loop uses. This might be another way to allow the ghc rts main loop to be the master one. I'd guess that it would be easier to expose some rts function that tells us what fds & timeouts ghc's rts is interested in at any particular time and write some glue code (in C) to install ghc's rts events sources in an external main loop. What would such an API look like? Presumably we'd need to know if there are runnable Haskell threads and we'd need to be able to run them for one timeslice. If there were no runnable threads, we'd want to know the set of fds & timeouts that the rts would want to block upon. [sorry, this next bit is a bit implementation specific] http://developer.gnome.org/doc/API/2.0/glib/glib-The-Main-Event-Loop.html#GS... To create a GSource from this we would need to implement a prepare, check & dispatch to fill out a GSourceFuncs struct. In prepare we'd check to see if there are currently any runnable Haskell threads (returning true if there were). It would also set up the set of fds to be polled. It would also return the timeout of the soonest timeout that the ghc rts has (or -1). In check we'd return true if any fds were ready or a timeout had expired. In dispatch we'd ask the ghc rts to run for one timeslice. Any simpler / better ideas anyone? Duncan
participants (1)
-
Duncan Coutts