views:

19

answers:

2

The Thread Safety Summary on developer.apple.com states that NSWindow's are thread safe* and can be created from worker threads.

I have a worker thread that i've created rather simply:

  [NSThread detachNewThreadSelector:@selector(threadProc:)
                           toTarget:self
                         withObject:nil];

that tries to create a NSWindow. I used to marshal the create call onto the main thread and it worked, reading the Thread Safety Summary I tried simply creating it on the worker thread but I get this crash:

Thu Oct 28 15:13:15 trans.mshome.net MyApp[99962] <Error>: kCGErrorRangeCheck: CGSNewWindowWithOpaqueShape: Cannot create window
Thu Oct 28 15:13:15 trans.mshome.net MyApp[99962] <Error>: kCGErrorFailure: Set a breakpoint @ CGErrorBreakpoint() to catch errors as they are logged.
2010-10-28 15:13:15.192 MyApp[99962:5903] An uncaught exception was raised
2010-10-28 15:13:15.194 MyApp[99962:5903] Error (1007) creating CGSWindow
2010-10-28 15:13:15.195 MyApp[99962:5903] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Error (1007) creating CGSWindow'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x91b5ebba __raiseError + 410
    1   libobjc.A.dylib                     0x96e9c509 objc_exception_throw + 56
    2   CoreFoundation                      0x91b5e8e8 +[NSException raise:format:arguments:] + 136
    3   CoreFoundation                      0x91b5e85a +[NSException raise:format:] + 58
    4   AppKit                              0x94e5ac2d _NXCreateWindow + 316
    5   AppKit                              0x94e5aa38 _NSCreateWindow + 59
    6   AppKit                              0x94e59c5e -[NSWindow _commonAwake] + 1784
    7   AppKit                              0x94e56886 -[NSWindow _commonInitFrame:styleMask:backing:defer:] + 1524
    8   AppKit                              0x94e554d9 -[NSWindow _initContent:styleMask:backing:defer:contentView:] + 1568
    9   AppKit                              0x94e54eb3 -[NSWindow initWithContentRect:styleMask:backing:defer:] + 71
    10  acmeFrame.dylib                     0x028e300b _ZN11Acme12CCocoaWindow12CreateWindowEPKciiiij + 517
    18  acmeFrame.dylib                     0x00011ac4 -[CocoaThread threadProc:] + 136
    19  Foundation                          0x92dd28d4 -[NSThread main] + 45
    20  Foundation                          0x92dd2884 __NSThread__main__ + 1499
    21  libSystem.B.dylib                   0x94b3b81d _pthread_start + 345
    22  libSystem.B.dylib                   0x94b3b6a2 thread_start + 34

Correction: It states that NSWindow objects are thread-unsafe - i.e. they can be accessed from multiple thread, but access to them must be serialized. Under "Window Restrictions" it however does state that windows CAN be created from a secondary thread.

+1  A: 

That's not what it says when I read it. :-)

Under the "Thread-Unsafe Classes" header, NSWindow is listed. Under "Window Restrictions" (emphasis mine), there are restrictions. Later in the guide, drawing considerations are mentioned in reference to windows.

In short, you'll probably need to post your window creation code.

The larger question to ask is why is it necessary in your case to create windows from a secondary thread? You can avoid all these problems by doing work in the other threads then updating the UI on the main thread ( with -performSelectorOnMainThread:withObject:waitUntilDone: ).

Joshua Nozzi
true that. My problem is, under window restrictions it does state that Windows CAN be created from secondary threads.
Chris Becke
Yes they can be *created* but you may be doing other things besides. Without more details there's not much I can do but guess. Also, per my last paragraph, I can almost guarantee you're making things mire difficult on yourself by manipulating the GUI from other threads. How about describing your goal?
Joshua Nozzi
I might be doing other things, but the Window Restrictions it doesn't preclude doing other things. As the window is not yet created, I havn't even stored the NSWindow* in a member variable yet so I don't seem to have broken any contracts.
Chris Becke
My "goal" is to have a single program, that loads dylibs, as plugins. Each plugin has a window, and its own thread (as the plugins do do timeconsuming stuff that mustn't interfere with the responsiveness of the other plugins). UI events and painting is done from the main thread (of course) but I thought I could shortcut some interthread comms by creating my plugins windows from each worker thread.
Chris Becke