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 (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to