How to ensure code executes in the context of a specific OS thread?
marlowsd at gmail.com
Wed Jul 6 17:09:59 CEST 2011
On 06/07/2011 15:42, Jason Dagit wrote:
> On Wed, Jul 6, 2011 at 2:23 AM, Simon Marlow<marlowsd at gmail.com> wrote:
>> On 06/07/2011 07:37, Jason Dagit wrote:
>>> On Jul 5, 2011 1:04 PM, "Jason Dagit"<dagitj at gmail.com
>>> <mailto:dagitj at gmail.com>> wrote:
>>> > On Tue, Jul 5, 2011 at 12:33 PM, Ian Lynagh<igloo at earth.li
>>> <mailto:igloo at earth.li>> wrote:
>>> > > On Tue, Jul 05, 2011 at 08:11:21PM +0100, Simon Marlow wrote:
>>> > >>
>>> > >> In GHCi it's a different matter, because the main thread is running
>>> > >> GHCi itself, and all the expressions/statements typed at the prompt
>>> > >> are run in forkIO'd threads (a new one for each statement, in fact).
>>> > >> If you want a way to run command-line operations in the main thread,
>>> > >> please submit a feature request. I'm not sure it can be done, but
>>> > >> I'll look into it.
>>> > >
>>> > > We already have a way: -fno-ghci-sandbox
>>> > I've removed all my explicit attempts to forkIO/forkOS and passed the
>>> > command line flag you mention. I just tried this but it doesn't
>>> > change the behavior in my example.
>>> I tried it again and discovered that due to an argument parsing bug in
>>> cabal-dev that the flag was not passed correctly. I explicitly passed it
>>> and verified that it works. Thanks for the workaround. By the way, I did
>>> look at the user guide for options like this and didn't see it. Which
>>> part of the manual is it in?
>>> Can I still make a feature request for a function to make code run on
>>> the original thread? My reasoning is that the code which needs to run on
>>> the main thread may appear in a library in which case the developer has
>>> no control over how ghc is invoked.
>> I'm not sure how that would work. The programmer is in control of what the
>> main thread does, not GHC. So in order to implement some mechanism to run
>> code on the main thread, we would need some cooperation from the main thread
>> itself. For example, in gtk2hs the main thread runs an event handler loop
>> which occasionally checks a queue for requests from other threads (at least,
>> I think that's how it works).
> What I'm wrestling with is the following. Say I make a GUI library.
> As author of the GUI library I discover issues like this where the
> library code needs to execute on the "main" thread. Users of the
> library expect the typical Haskell environment where you can't tell
> the difference between threads, and you fork at will. How can I make
> sure my library works from GHC (with arbitrary user threads) and from
> As John Lato points out in his email lots of people bump into this
> without realizing it and don't understand what the problem is. We can
> try our best to educate everyone, but I have this sense that we could
> also do a better job of providing primitives to make it so that code
> will run on the main thread regardless of how people invoke the
> In my specific case (Cocoa on OSX), it is possible for me to use some
> Cocoa functions to force things to run on the main thread. From what
> I've read Cocoa uses pthreads to implement this. I was hoping we could
> expose something from the RTS code in Control.Concurrent so that it's
> part of an "official" Haskell API that library writers can assume.
> Judging by this SO question, it's easier to implement this in Haskell
> on top of pthreads than to implement it in C (here I'm assuming GHC's
> RTS uses pthreads, but I've never checked):
> In fact, the it sounds like what Gtk2hs is doing with the postGUI functions.
Right, but usually the way this is implemented is with some cooperation
from the main thread. That SO answer explains it - the main thread runs
some kind of loop that periodically checks for requests from other
threads and services them. I expect that's how it works on Cocoa.
So you can't just do this from a library - the main thread has to be in
on the game.
I suppose you might wonder whether the GHC RTS could implement
runInMainThread by preempting the main thread and running some different
code on it. In theory that's possible, but whether it's a good idea or
not is a different matter! I think it amounts to the same thing as the
gtk2hs folks have been asking for - multiple Haskell threads bound to
the same OS thread. runInMainThread then becomes the same as forking a
temporary new thread bound to the main OS thread, or temporarily binding
the current thread to the main OS thread. If the main OS thread is off
making a foreign call (e.g. in the GUI library's main loop) then it
can't run any other Haskell threads anyway, and then I have to figure
out what to do with all these Haskell threads waiting for their bound OS
thread to come back from the foreign call. My guess is that all this
would be pretty complex to implement.
Still, I'm all for making things easier somehow. At the least, we
should have good diagnostics when you're using GHCi and this goes wrong.
Although I'm not sure how to do that, I think it's really something
the gtk2hs or Cocoa binding needs to implement. Do you have a way to
check whether you're on the main thread or not?
More information about the Cvs-ghc