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 protected])

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 [email protected]

Reply via email to