Search code examples
objective-ccocoa

Low-level details of the implementation of performSelectorOnMainThread:


Was wondering if anyone knows, or has pointers to good documentation that discusses, the low-level implementation details of Cocoa's 'performSelectorOnMainThread:' method.

My best guess, and one I think is probably pretty close, is that it uses mach ports or an abstraction on top of them to provide intra-thread communication, passing selector information along as part of the mach message.

Right? Wrong?

Update 09:39AMPST

Thank you Evan DiBiase and Mecki for the answers, but to clarify: I understand what happens in the run loop, but what I'm looking for an answer to is; "where is the method getting queued? how is the selector information getting passed into the queue?" Looking for more than Apple's doc info: I've read 'em

Update 14:21PST

Chris Hanson brings up a good point in a comment: my objective here is not to learn the underlying mechanisms in order to take advantage of them in my own code. Rather, I'm just interested in a better conceptual understanding of the process of signaling another thread to execute code. As I said, my own research leads me to believe that it takes advantage of mach messaging for IPC to pass selector information between threads, but I'm specifically looking for concrete information on what is happening, so I can be sure I'm understanding things correctly. Thanks!

Update 03/06/09

I'm look for the lowest-level detail of the mechanism used by performSelectorOnMainThread: and the like, and as I mentioned earlier, I suspect it has something to do with Mach ports but I'd really like to know for sure.


Solution

  • Yes, it does use Mach ports. What happens is this:

    1. A block of data encapsulating the perform info (the target object, the selector, the optional object argument to the selector, etc.) is enqueued in the thread's run loop info. This is done using @synchronized, which ultimately uses pthread_mutex_lock.
    2. CFRunLoopSourceSignal is called to signal that the source is ready to fire.
    3. CFRunLoopWakeUp is called to let the main thread's run loop know it's time to wake up. This is done using mach_msg.

    From the Apple docs:

    Version 1 sources are managed by the run loop and kernel. These sources use Mach ports to signal when the sources are ready to fire. A source is automatically signaled by the kernel when a message arrives on the source’s Mach port. The contents of the message are given to the source to process when the source is fired. The run loop sources for CFMachPort and CFMessagePort are currently implemented as version 1 sources.

    I'm looking at a stack trace right now, and this is what it shows:

    0 mach_msg
    1 CFRunLoopWakeUp
    2 -[NSThread _nq:]
    3 -[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:]
    4 -[NSObject(NSThreadPerformAdditions) performSelectorOnMainThread:withObject:waitUntilDone:]
    

    Set a breakpoint on mach_msg and you'll be able to confirm it.