Re: Grand Central Dispatch vs CFRunLoop
Re: Grand Central Dispatch vs CFRunLoop
- Subject: Re: Grand Central Dispatch vs CFRunLoop
- From: Chris Kane <email@hidden>
- Date: Wed, 16 Sep 2009 11:47:41 -0700
Forgive my responding to two sets of comments with one message ...
On Sep 13, 2009, at 9:18 PM, Ken Thomases wrote:
On Sep 13, 2009, at 10:09 AM, Filip van der Meeren wrote:
I am using NSTask objects in a Command Line Tool project, to be
able to intercept notifications I need a runloop to the best of my
knowledge.
Well, not intercepting ... To receive the
NSTaskDidTerminateNotification notification, you do need to run the
run loop on the thread which launches the task, after launching. If
you never want that notification, then you do not need to run a run
loop.
Don't confuse two different things. Notifications do not require a
run loop in order to be delivered. The observer's selectors are
just directly invoked when the notification is posted.
However, there are certain APIs which promise to post the notification
back on the thread "which started the operation". Those APIs require
the run loop to be run on that thread (for the notification to
occur). NSTask and NSFileHandle are two such APIs; NSSound used to be
the same with respect to calling delegate methods, not sure if it
still is; NSURLConnection may be one too, I'm not 100% sure off the
top of my head; and there are probably others I'm not remembering
right now.
Those APIs are locked into that contract for all eternity (or until
deprecated then removed from the libraries). There will have to be
new APIs without that commitment to get out from the necessity of the
run loop running.
However, NSTask has to monitor an external event in order to
determine when the task has terminated. For that, it installs a run
loop source into the run loop of the thread from which it is launched.
Once it has determined that the task has terminated, NSTask does
post a notification. But it's the monitoring of the task that
requires the run loop to be run, not the delivery of the notification.
Actually, for a long time NSTask spawned a background thread. Then it
used a CFFileDescriptor in Leopard. In SnowLeopard it uses GCD.
Except for Leopard (which had two reasons for needing the run loop),
the run loop is just needed to [get the work back to that original
thread and] post the notification due to the API commitment.
And ever since I installed Mac OS X 10.6, I wondered if I could
replace that entire runloop by a dispatch_queue.
That's thinking about things the wrong way around. A run loop is a
higher-level abstraction than a dispatch queue. In general, you
should always program in terms of the highest-level abstraction that
suits your purposes. So, you _want_ to run the run loop instead of
running the dispatch queue manually. As documented for
dispatch_get_main_queue(), running the main thread's run loop
automatically processes the main dispatch queue.
You can't run dispatch queues manually, per se, but if your whole
process is converted to libdipatch you can drive the whole thing with
dispatch_main() (as long as you never want that to exit/return).
However, as Ken says, if you are doing things at a higher level which
need the run loop then you should stick with NSRunLoop (particularly
on the main thread).
Filip did not say if the command-line tool was multithreaded, but I'll
put in some general words about that to everybody:
Feel free to move your code away from using CFRunLoop and NSRunLoop on
non-main threads, and switching to dispatch_sources, if you want to be
a little more advanced and modern. This is not necessarily something
for the faint-of-heart, but then multithreading wasn't already.
Switching off of kevent() on your own background thread and moving to
GCD/dispatch is definitely a good thing; same for other background
threads which are just sitting there blocked (say, doing read() on a
background thread, which you did to get it off the main thread). Any
thread which is sitting there running a run loop to "receive commands"
is a good candidate for switching to NSOperation/NSOperationQueue.
However, if the run loop is being run because you want to get a
notification or similar kinds of API commitments, then you need to be
careful. You can't just eliminate the running of that loop and have
things keep working. But similarly don't just move all the thread
code into an NSOperation (with run loop running intact) and throw it
in an operation queue; having an NSOperation block running the run
loop is not a smart use of NSOperationQueues. For example, in the
case of launching an NSTask, instead of launching the NSTask on the
background or temporary operation thread, launch it on the main thread
if the main thread's run loop is already going to be running (use
performOnMainThread:... if you have to to launch the task on the main
thread). That way you don't have to run a background thread run loop.
A general danger in all this is that some API you are using refers to
the "current run loop" and does something to it which is crucial
later. This has always been true for background threads, but the
pitfall becomes more pronounced as more developers move to
multithreading, particularly using the "indirect" kinds of mechanisms
like dispatch queues and NSOperationQueues.
With respect to NSTask, there's no reason to believe that it will
work if you just run the main dispatch queue rather than running the
NSRunLoop. I highly doubt it would.
I think it will work fine as long as you don't want the
NSTaskDidTerminateNotification and related (ie, -isRunning to return
the right answer) and anything else the NSTask might do as a result of
the child process dying.
However, if you are also using NSFileHandle "in-background"
operations, then you will need the run loop run (on the thread(s)
which start those background reads) to get those notifications.
That's a separate matter from NSTask, but people may confuse the two
together so I mention it here.
Chris Kane
Cocoa Frameworks, Apple
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden