[Haskell-cafe] How to ensure code executes in the context of a specific OS thread?

David Pollak feeder.of.the.bears at gmail.com
Mon Jul 4 16:09:09 CEST 2011


On Sun, Jul 3, 2011 at 10:02 PM, Jason Dagit <dagitj at gmail.com> wrote:

> Hello,
>
> I'm trying to get some GUI code working on OSX and numerous forums
> around the internet keep reiterating that on OSX to correctly handle
> GUI events you need to use the original thread allocated to your
> process to check for events and to call the Cocoa framework
> functionality.  Specifically, using a secondary thread (even a bound
> thread) is not sufficient with the Cocoa framework.
>
> I looked at the threading documentation in Control.Concurrent for GHC
> and it's not clear to me if this is even possible with GHC without
> restricting to the non-threaded RTS.  This means that using the GUI
> library from GHCI is not an option and using multiple OS threads in
> the final application is also not possible.  This means that some FFI
> libraries will be unusable.
>
> My main question is, is there a way around this so that I could, for
> example, use the library from GHCI?
>
> My second question is, if there is no current workaround then how can
> we remedy this situation?  It seems like there could be an api
> function like:
> runOnOriginalThread :: IO a -> IO a
>

I've got some code in https://github.com/dpp/LispHaskellIPad that uses an
FFI call into ObjC code that invokes a function on the UI thread.

In Haskell:

runOnMain :: IO () -> IO ()
runOnMain todo = do
                  func <- funky
                  dispatchFunc func
  where funky =  mkStrCB $ \v -> do
                                   todo

And in ObjC:

void dispatchFunc(void (*fp)(void*)) {
    // dispatch_async_f(dispatch_get_main_queue(), NULL, fp);
    id runner = [[PerformOMatic alloc] init];
    [runner setFunc:fp];
    [runner run];
}

And:

#import "PerformOMatic.h"


@implementation PerformOMatic
- (void)run {
    [self performSelectorOnMainThread:@selector(reallyDoIt:) withObject:self
waitUntilDone:TRUE];
}

- (void)reallyDoIt:(id)ignore {
    whatToDo(NULL);
    releaseMe(whatToDo);
    [self dealloc];
}

- (void)setFunc:(void *)func {
    whatToDo = func;
}

@end


Pardon the extremely ugly code, I'm a Haskell newbie and my ObjC skills are
20 years old.


>
> This function would be similar to runInBoundThread except it would be
> guaranteed to run on the original thread allocated to the ghc/ghci
> process.  I believe the above primitive would be sufficient.
>
> I'll worry about filing a bug or making a libraries proposal after I
> have a better understanding of what must be done.
>
> Thanks,
> Jason
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>



-- 
Lift, the simply functional web framework http://liftweb.net
Simply Lift http://simply.liftweb.net
Follow me: http://twitter.com/dpp
Blog: http://goodstuff.im
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20110704/f341dc3b/attachment.htm>


More information about the Haskell-Cafe mailing list