Re: Challenge: Block Main Thread while Work is done, with Timeout
Re: Challenge: Block Main Thread while Work is done, with Timeout
- Subject: Re: Challenge: Block Main Thread while Work is done, with Timeout
- From: Ken Thomases <email@hidden>
- Date: Thu, 23 Jul 2009 19:44:34 -0500
On Jul 23, 2009, at 6:44 PM, Jerry Krinock wrote:
I'd often like to block the main thread
First question is: why? Blocking the main thread is usually bad and
to be avoided. What are you actually trying to achieve? Can you give
an example of when that would be desirable?
while another thread or process performs a little task, but subject
to a short timeout.
If it's another thread, I would recommend NSConditionLock.
If it's another process, then _something_ is going to have to monitor
an external source of data or events. A run loop is a fair way of
doing that, but you could also use direct I/O over a socket or pipe.
You can use kqueue, select, or poll to wait for data with a timeout.
A few weeks ago, I was able to achieve this by "running" the main
thread's run loop while an NSTask completed.
Running a run loop is not quite the same thing as blocking the
thread. A run loop will block while there's nothing to do, but will
process input sources and timers if they fire. Typically when one
says "block" one means wait exclusively for a single operation to
complete.
I know the trouble is that, although I have read the NSRunLoop
documentation and related material in the Threading Programming
Guide many times, I just don't understand the magic behind this:
while ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]])
{
// do something
}
I know that it only runs when an "input source" fires, and so I
believe I need to add an input source, but when I try to do that I
end up creating ports and distributed objects, which is obviously
wrong.
You shouldn't need to use distributed objects. It's relatively common
to create a dummy port to add to a run loop just to keep it alive.
You can get one with [NSPort port] and just never use it for
anything. Or, you could use it for one thread to signal that it's
done to another thread.
By the way, if you're using NSDefaultRunLoopMode on the main thread,
there are probably _lots_ of input sources and timers registered, so
you'll _really_ not be blocking.
Can anyone show how to fix this?
I think you're imagining that notifications are delivered through the
run loop. They are not. When -doWorkForTimeInterval: posts a
notification, it's basically equivalent to directly invoking the
selectors of the various observers right there and then. Of course,
the notification center is doing the housekeeping of tracking
observers and sending the messages, but the point is the delivery of
notifications is not analogous to events or timers or input sources.
The notifications don't cross threads; they are delivered in the
thread where they are posted.
If you really want to use a run loop in this manner, you could use a
port. The SSYThreadBlocker would be the port's delegate to handle
messages it receives; it would run the run loop to allow messages to
be received and processed; the worker thread would send them. You
might consider using a private run-loop mode, though, so the run loop
is only processing your input source.
Do consider NSConditionLock as an alternative, though. It's likely to
be much simpler and more straightforward.
Regards,
Ken
_______________________________________________
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