Re: Asynchronous Notification Does NOT Work
Re: Asynchronous Notification Does NOT Work
- Subject: Re: Asynchronous Notification Does NOT Work
- From: Ken Thomases <email@hidden>
- Date: Mon, 06 Jun 2011 07:03:33 -0500
Hi Bing,
On Jun 5, 2011, at 11:36 PM, Bing Li wrote:
> In my system, a server needs to handle requests from remote clients. Multiple local threads are raised to listen to the specific port concurrently.
This is an unusual design. It is more common for one thread (often the main thread) to listen for connection requests. When a connection is made, then the work associated with that connection may be spun off into its own thread.
It is not normal for multiple threads to all listen for connections on the same port.
> When a request is received by one of the thread, it must notify other responding threads asynchronously.
What do the other threads do with this notification? Why must they be notified? Is it just to coordinate shared access to the port? If so, you're better off eliminating that shared access, as described above.
> The reason to notify asynchronously is to avoid possible blocking by the responding threads. But I think it is not necessary to use asynchronous notification if the responding threads are non-blocking.
Notifications were never going to be asynchronous in this sense. Using NSNotificationQueue is not really asynchronous, it's only deferred. When notifications are delivered, they are always delivered synchronously. It's just that delivery can be delayed so that it doesn't occur at the moment it's queued; it can happen later, when control is returned to the run loop. And that's in addition to the fact that notifications don't cross threads.
If you have a reference to the NSThread you wish to notify, you can use -performSelector:onThread:withObject:waitUntilDone: with NO for the wait parameter to submit a message to that thread. However, once again, such performed selectors rely on the run loop. If you're not going to run the run loop on your thread, the thread won't receive these messages.
That brings us to another question: how do you imagine that an asynchronous communication could be received by a thread which isn't specifically arranging to receive it? As a practical matter, there's no useful mechanism to interrupt a thread which is not cooperating and cause it to run some method or function. The target thread must be cooperating with your attempt to communicate with it. It must have made arrangements to receive your message. For example, it must include a pipe, socket, Mach port, or some similar communication mechanism in the set of I/O inputs it's waiting for. The easiest way to achieve this is using the run loop.
If your thread runs its run loop, then it's automatically cooperating with communication mechanisms built into the frameworks, such as -performSelector:onThread:withObject:waitUntilDone:. Or, you can add your own run loop source to the run loop to build another mechanism. For example, you could add an NSMachPort to the run loop, and other threads can send messages to that run loop to have them received by the target thread. This technique is illustrated in Apple's documentation about run loops <http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html>.
If you're not comfortable with run loops, you can use a pipe and select(), kqueue(), or poll() to achieve something similar. The idea is to alter your code such that, at each place where you would otherwise perform blocking I/O on a single file descriptor, you instead block in select() waiting on multiple file descriptors. You should then configure all of the file descriptors for non-blocking I/O. When each file descriptor is ready, you read what's immediately available from it and do the appropriate work on the received data. Then you go back to select() to wait for any of your file descriptors to have more data. Once you have an architecture like this, you can create a pipe for inter-thread communication. Each thread would have its own pipe. It would add the read end of that pipe to the set passed to select(). When other threads want to communicate with that thread, they'd write to the other end of the pipe. (This is the sort of hard-coded, non-generalizable, and inflexible mechanism that a run loop is designed to replace with a generalized and flexible mechanism, but you may be more familiar with it.)
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