RE: Port and runloop problem - solutions with thread safe queues and DO
RE: Port and runloop problem - solutions with thread safe queues and DO
- Subject: RE: Port and runloop problem - solutions with thread safe queues and DO
- From: Miguel Morales <email@hidden>
- Date: Mon, 27 Aug 2001 09:31:29 -0700
Dear Raphael,
I have a different take on your port problem. There is a fairly small
number of messages that can be queued, before they start being dropped
by the system (something like 8), so if the main thread is not keeping
up, you can overload the message queue. I see 2 solutions.
If only the last message is critical, remove the oneway flag on the
remote message call for finished (if this is how it is implemented), and
see if this fixes the problem.
Another way to do this is the thread safe queue, or some variation on
it, coupled with DO calls. The technique is to put the information on
the queue, then notify the other thread that the information is there.
Because both threads can see the queue, you can use this to manage the
message queue. Additionally, since the thread safe queue is in the same
memory space, you can cut your messaging traffic dramatically. I'll
give 2 examples.
1 - you only want the main thread to use the latest refresh, not wast
time doing each refresh in order, and catch the finish command. The
thread puts the information for the refresh into the queue (NSLocking is
critical), and calls the main thread to refresh via DO. When the thread
comes back to update the information, the main thread may or may not
have pulled this off of the queue. If the information has been pulled,
the thread puts the new information in, then calls refresh again (no
messages are piling up). However, if the information is still in the
queue, it is replaced with the new information, and refresh is not
called again (the main thread already has a refresh command queued up,
and will get to it eventually). The finish command is just sent by DO.
This keeps the message stack very small, and eliminates any unnecessary
work.
2- you want all messages to be dealt with. You can simply use the queue
to stack information, and to block the thread with an NSConditionalLock
if the main thread falls too far behind. Or, you can have the main
thread poll (by calling the same method with an NSTimer) until the queue
is empty. If the thread puts information onto an empty queue, it then
restarts the polling of the main thread with a DO call. (There are
subtleties with this last solution, the thread is only marked as empty
if the main thread asks for information and there is none, to keep the
messaging synched up right. I have code for this if you are
interested). The Finish is then just sent via DO, and again the
messaging traffic has been kept to a minimum.
These thread safe queues are a little more work, but offer much more
flexibility in exactly how messaging is handled, and can dramatically
speed up communication between the threads if significant amounts of
information needs to be passed.
Hope this helps,
-Miguel
On Sunday, August 26, 2001, at 12:12 AM, cocoa-dev-
email@hidden wrote:
Hi all,
I have a basic setup where a worker thread does the actual computing and
signals the main via an NSPort when it should refresh...
The problem is that when there are "too many" of these NSPortMessage,
some seem to be skipped. It is generally acceptable for me except for
the last message, which tells the thread has finished processing (and
stops a modal loop on the main thread). If I don't get it, my
application is locked. To give an example of the messages that go
through that port :
refresh
refresh
(...)
refresh
finished
And I sometimes don't get the "finished" one.
Is there a way to tell a message has to be absolutely delivered, or
should I use other inter-thread comm technique (polling with a timer,
but I'd prefer not...) ?
Raphael