Re: Grand Central Dispatch vs CFRunLoop
Re: Grand Central Dispatch vs CFRunLoop
- Subject: Re: Grand Central Dispatch vs CFRunLoop
- From: Filip van der Meeren <email@hidden>
- Date: Wed, 16 Sep 2009 22:42:22 +0200
Thank you, that helped a lot.
Filip
On 16 Sep 2009, at 20:47, Chris Kane wrote:
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