www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Zero timeout receive

reply "James Wirth" <jwirth1 suddenlink.net> writes:
The discussion:

     
http://forum.dlang.org/thread/mailman.426.1286264462.858.digitalmars-d puremagic.com?page=9

implies that:
    receiveTimeout(dur!"msecs"(0), some-callback-function)

is acceptable - meaning that no blocking occurs.  A simple 
experiment verifies this - but I hesitate to use "undocumented" 
features.  Some APIs would interpret the 0 as infinity.

I also fear that placing such a nonblocking recieve into the main 
event loop of a GUI program would impact performance - it would 
also be non-generic.  Is there a fast function which returns true 
just when the "mail box" is non-empty?

Thanks
Apr 12 2013
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Saturday, 13 April 2013 at 01:26:16 UTC, James Wirth wrote:
 The discussion:

     
 http://forum.dlang.org/thread/mailman.426.1286264462.858.digitalmars-d puremagic.com?page=9

 implies that:
    receiveTimeout(dur!"msecs"(0), some-callback-function)

 is acceptable - meaning that no blocking occurs.  A simple 
 experiment verifies this - but I hesitate to use "undocumented" 
 features.  Some APIs would interpret the 0 as infinity.

 I also fear that placing such a nonblocking recieve into the 
 main event loop of a GUI program would impact performance - it 
 would also be non-generic.  Is there a fast function which 
 returns true just when the "mail box" is non-empty?

 Thanks
Make a small test and time it. I personally wouldn't expect to see much slowdown from the extra code invoked by receiveTimeout compared to the rest of a busy loop. However, either special casing receiveTimeout for 0 duration or introducing a new receiveNoBlock or similar would be good.
Apr 13 2013
parent reply "James Wirth" <jwirth1 suddenlink.net> writes:
On Saturday, 13 April 2013 at 08:54:03 UTC, John Colvin wrote:
 On Saturday, 13 April 2013 at 01:26:16 UTC, James Wirth wrote:
 The discussion:

    
 http://forum.dlang.org/thread/mailman.426.1286264462.858.digitalmars-d puremagic.com?page=9

 implies that:
   receiveTimeout(dur!"msecs"(0), some-callback-function)

 is acceptable - meaning that no blocking occurs.  A simple 
 experiment verifies this - but I hesitate to use 
 "undocumented" features.  Some APIs would interpret the 0 as 
 infinity.

 I also fear that placing such a nonblocking recieve into the 
 main event loop of a GUI program would impact performance - it 
 would also be non-generic.  Is there a fast function which 
 returns true just when the "mail box" is non-empty?

 Thanks
Make a small test and time it. I personally wouldn't expect to see much slowdown from the extra code invoked by receiveTimeout compared to the rest of a busy loop. However, either special casing receiveTimeout for 0 duration or introducing a new receiveNoBlock or similar would be good.
Im using wine on Linux to develop MS code (dont have an MS box) so am not too confident of timing accuracy - however, I tried it in the really simple MS GUI library Im making, and it seems to work ok. Special casing receiveTimeout would introduce less name bloat but might impact other receive performance. As a Java programmer I tend to ignore slowdowns of 2:1 and as a Python programmer even 70:1 - but I could see that system programmers might disagree. Thanks for your thoughts.
Apr 15 2013
parent reply Sean Kelly <sean invisibleduck.org> writes:
On Apr 15, 2013, at 7:22 PM, James Wirth <jwirth1 suddenlink.net> wrote:
=20
 Special casing receiveTimeout would introduce less name bloat but =
might impact other receive performance. As a Java programmer I tend to = ignore slowdowns of 2:1 and as a Python programmer even 70:1 - but I = could see that system programmers might disagree. Currently, receiveTimeout will call Condition.wait(n) for any wait time = passed. For a wait time of 0, this will be equivalent to a yield(), so = the calling thread will be suspended for a context switch if there are = other threads waiting to run. I could special case this to not wait at = all, but am inclined to say that the yield() effect is a good thing = here, as it helps concurrency.=
Apr 16 2013
parent "James Wirth" <jwirth1 suddenlink.net> writes:
On Tuesday, 16 April 2013 at 21:38:39 UTC, Sean Kelly wrote:
 On Apr 15, 2013, at 7:22 PM, James Wirth 
 <jwirth1 suddenlink.net> wrote:
 
 Special casing receiveTimeout would introduce less name bloat 
 but might impact other receive performance.  As a Java 
 programmer I tend to ignore slowdowns of 2:1 and as a Python 
 programmer even 70:1 - but I could see that system programmers 
 might disagree.
Currently, receiveTimeout will call Condition.wait(n) for any wait time passed. For a wait time of 0, this will be equivalent to a yield(), so the calling thread will be suspended for a context switch if there are other threads waiting to run. I could special case this to not wait at all, but am inclined to say that the yield() effect is a good thing here, as it helps concurrency.
Many Thanks, I appreciate the "hand holding". Will use receiveTimeout(0,...) without fear henceforth. I think yielding in the windows event thread will indeed benefit the application.
Apr 18 2013
prev sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Apr 12, 2013, at 6:26 PM, James Wirth <jwirth1 suddenlink.net> wrote:

 The discussion:
=20
    =
http://forum.dlang.org/thread/mailman.426.1286264462.858.digitalmars-d pur= emagic.com?page=3D9
=20
 implies that:
   receiveTimeout(dur!"msecs"(0), some-callback-function)
=20
 is acceptable - meaning that no blocking occurs.  A simple experiment =
verifies this - but I hesitate to use "undocumented" features. Some = APIs would interpret the 0 as infinity. Then consider it documented. receiveTimeout(0, =85) is intended to work = as it does currently. If you want it to block forever, use receive(=85).
 I also fear that placing such a nonblocking recieve into the main =
event loop of a GUI program would impact performance - it would also be = non-generic. Is there a fast function which returns true just when the = "mail box" is non-empty? The receive calls are as lightweight as I can make them. In essence: 1. Walk a thread-local list of received messages looking for a match. = If found, pass to the callback, remove the message, and return. 2. Lock a shared list of recently received messages. If the list is = empty, block on a condition variable until a message is received, then = go to step 3. 3. Move all messages from the shared list to a local list and release = the lock. 4. Walk this new list of messages looking for a match. If found, pass = the callback, remove the message, append these new messages to the = thread-local list and return. 5. If no match, append these new messages to the thread-local list and = go to step 2. So if the message you want is already present in your local message = queue, receive doesn't even need to acquire a mutex. If not, it = acquires the mutex for just as long as it takes to move the new messages = from the shared list to the local list (basically reassigning a few = pointers). If no match anywhere, then it will block for as long as = indicated, either forever for receive() or until the timeout has elapsed = with receiveTimeout(). By the way, I just noticed that the receiveTimeout() version uses the = same timeout for each condvar wait when it should be reducing it on each = iteration to ensure that the maximum wait time is as indicated. This is = a bug and needs to be fixed. And because of how Condition is = implemented, this will mean a kernel call to determine time elapsed on = each iteration where a message was received before the timeout. So this = case at least will be a bit less optimal that what could be done = targeting Posix specifically.=
Apr 16 2013