starting cocoa in different thread

  • Hi,

    For reasons I won't go into (unless you are interested) I want to
    start Cocoa on a thread that is not the main posix thread.  I wrote
    the small test program below that creates a little window with a
    button in it.  There is a variable 'BOOL use_thread' in the main
    function.  If it is 'NO', then the program runs fine -- I can can
    click the button, see that events are being generated.  If use_thread
    = YES, then it doesn't work -- sendEvent: gets called constantly with
    null NSEvent pointers.

    I thought I would be able to use any pthread as the "main" Cocoa
    event thread, as long as that thread called [NSApplication
    sharedApplication], set up the UI, and called [NSApp run].  Is that
    possible?  If so, how?

    thank you,
    Rob

    file: two_threads.m
    compiled with: gcc -o two_threads two_threads.m -framework Cocoa

    #import <Foundation/Foundation.h>
    #import <AppKit/AppKit.h>

    #include <pthread.h>

    static int eventCount = 0;

    @interface MyApp : NSApplication
    @end

    @implementation MyApp
    {
    }
    - (void)sendEvent:(NSEvent*)e
    {
        printf("MyApp.sendEvent: %p %d %s\n",
                e, ++eventCount,
                [[e description] UTF8String]);
        [super sendEvent: e];
    }
    @end

    static void multithread_cocoa()
    {
        // Put Cocoa into multithreaded mode by starting an NSThread
    that does nothing.
        id obj = [[NSObject alloc] init];
        SEL m = @selector(isEqual:);
        [NSThread detachNewThreadSelector:m toTarget:obj withObject:obj];
    }

    void *run_cocoa(void *ig)
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSApplication *app = [MyApp sharedApplication];

        id window = [[NSWindow alloc] initWithContentRect: NSMakeRect
    (10,10,100,100)
                                      styleMask: NSTitledWindowMask |
    NSResizableWindowMask | NSClosableWindowMask |
    NSMiniaturizableWindowMask
                                      backing: NSBackingStoreBuffered
                                      defer: NO];
        [window makeKeyAndOrderFront: window];

        id b = [NSButton new];
        [b setTitle: @"Hi"];
        NSRect r = NSMakeRect(0,0,100,100);
        [b setFrame: r];
        [[window contentView] addSubview: b];

        [app run];
        [pool release];
    }

    int main(int argc, char **argv)
    {
        BOOL use_thread = YES;

        if (use_thread)
        {
            multithread_cocoa();
            pthread_t t;
            pthread_create(&t, NULL, run_cocoa, NULL);
            pthread_join(t, NULL);
        }
        else
        {
            run_cocoa(NULL);
        }
        return 0;
    }
  • On Oct 25, 2007, at 1:23 PM, Robert Nikander wrote:

    > Hi,
    >
    > For reasons I won't go into (unless you are interested) I want to
    > start Cocoa on a thread that is not the main posix thread.  I wrote
    > the small test program below that creates a little window with a
    > button in it.  There is a variable 'BOOL use_thread' in the main
    > function.  If it is 'NO', then the program runs fine -- I can can
    > click the button, see that events are being generated.  If
    > use_thread = YES, then it doesn't work -- sendEvent: gets called
    > constantly with null NSEvent pointers.
    >
    > I thought I would be able to use any pthread as the "main" Cocoa
    > event thread, as long as that thread called [NSApplication
    > sharedApplication], set up the UI, and called [NSApp run].  Is that
    > possible?  If so, how?

    Short answer is "No, it's not documented to work".

    Things like performSelectorOnMainThread quite possibly use
    pthread_main_np() which would tie it to the "real" main thread, as
    well as further funky stuff about where events go (as you've seen).
    In fact, a bit of searching reveals that CFRunLoop hard codes in
    pthread_main_np to detect if the current run loop is the main run
    loop (or, more accurately, if pthread_main_np then CFRunLoopGetCurrent
    () returns CFRunLoopGetMain()).

    Glenn Andreas                      <gandreas...>
      <http://www.gandreas.com/> wicked fun!
    quadrium2 | build, mutate, evolve, animate  | images, textures,
    fractals, art
previous month october 2007 next month
MTWTFSS
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
Go to today