FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

SocketConduit fix for non-blocking IO

 
Post new topic   Reply to topic     Forum Index -> Mango
View previous topic :: View next topic  
Author Message
RedShodan



Joined: 04 Dec 2004
Posts: 5
Location: Colorado, US

PostPosted: Mon Dec 20, 2004 8:25 pm    Post subject: SocketConduit fix for non-blocking IO Reply with quote

Howdy.

I found a slight problem with the select handling of SocketConduit.reader() when you have a timeout set and the socket set to non-blocking. Basicly the return of select needs to be checked for the 0 value and return before trying to read. Here is a patch against mango_release_1.0a. Thanks.

Code:

diff -rc mango/mango/io/SocketConduit.d patch/mango/io/SocketConduit.d
*** mango/mango/io/SocketConduit.d      2004-11-30 13:28:06.000000000 +0000
--- patch/mango/io/SocketConduit.d      2004-12-20 19:07:43.957714600 +0000
***************
*** 316,323 ****
                     ss.add(this);

                     // wait until data is available
!                    if (select (ss, null, null, &tv) <= 0)
!                        return Eof;
                     }

                  int count = receive (src);
--- 316,326 ----
                     ss.add(this);

                     // wait until data is available
!                  int ret=select (ss, null, null, &tv);
!                    if (ret < 0)
!                    return Eof;
!                  else if (ret == 0)
!                    return 0;
                     }

                  int count = receive (src);
[/code]
Back to top
View user's profile Send private message
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Tue Dec 21, 2004 10:26 pm    Post subject: Reply with quote

Thanks!

I had vaguely hoped to avoid exposing those kinds of complexities, as you have probably gathered. May I ask why you're using an asynchronous socket in conjunction with a timeout? Is it to get around the simplistic socket model exposed by Mango.io, or for a deeper reason? I ask because there may be other areas to address, where some internal Mango peeking at the socket synchronous/asynchronous state might be a more compelling solution?

In a similar vein, are there any other scenarios you know of whereby select() returns a zero?

Appreciate your post and your input!
Back to top
View user's profile Send private message
RedShodan



Joined: 04 Dec 2004
Posts: 5
Location: Colorado, US

PostPosted: Sun Dec 26, 2004 8:29 pm    Post subject: Reply with quote

No problem. Smile

I'm using nonblocking along with a select timeout so that I can do both read and writes on a socket within a single thread, and have that thread be able to exit easily. I use a 200ms timeout, provides good response and doesnt impact the system hardly any. After that timeout is up during the call to select, with that patch, my code looks at the zero return and says 'Oh, nothing to do, lets loop around'. When it loops around it checks to make sure that it should still be running. Without that patch, the select would timeout and then the read() would be called. Because the select timed out we know that there is nothing to read. With the rest of the IO framework that causes an error when the file descriptor is set to non-blocking. So this will just bypass the read. For example of how its used, heres a chunk of my code:

Code:

  void run()
  {
    .....
    while (running())
    {
      if (!doWrite())
        break;
      if (!doRead())
        break;
    }
    stop();
    .....
  }

  protected bool doRead()
  {
    int readLen;

    myConduit.setTimeout(200);
    readLen=myConduit.read(myReadBuffer);
    if (readLen == SocketConduit.Eof)
      return false;
    else if (readLen == 0)
      return true;
    .....
  }



So assuming no pending output, the vast majority of time will be spent in the call to select from the SocketConduit.read(). Thats the perfect place to spend time, looking to see if we can read/write data. But if the timeout is reached, drop out and let the calling code be able to differentiate between an error and a timeout. This will let the calling code go off and 'do something' then come back repeat. In this case its looking to see if its still running. Another thread can (and will) set the running state to false at some point.

Incidently, the doWrite handles partial writing of bytes, keeps the remainder buffered, then tries to write more the next time its called. The doRead has to do the same, but inverted. With nonblocking IO it can read a partial 'packet of data'. So it has to know how much it needs to read, and keep trying to read, buffering as it goes until its got the right amount.

Its basicly a mixture of the 'a thread for every system call that could block' and the 'non-threaded socket server that has to be able to check other things every so often'.

I understand about trying to keep it simple Smile. But, I think in this case its needed. Also, I dont do windows (I have before though), but I *think* this would work.

Thanks for the response Smile
RedShodan
Back to top
View user's profile Send private message
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Wed Dec 29, 2004 2:38 pm    Post subject: Reply with quote

That all seems reasonable to me. Can anyone think of a good reason for a non-blocking write, also? Or a good reason to not support such non-blocking operations? For example, should a read-length of 0 be illegal?

If no-one comes up with a solid argument against, I'll add RedShodan's patch to the next release.

Cheers;
Back to top
View user's profile Send private message
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Sat Jan 01, 2005 8:47 pm    Post subject: Reply with quote

RedShodan wrote:
Code:

  void run()
  {
    .....
    while (running())
    {
      if (!doWrite())
        break;
      if (!doRead())
        break;
    }
    stop();
    .....
  }

  protected bool doRead()
  {
    int readLen;

    myConduit.setTimeout(200);
    readLen=myConduit.read(myReadBuffer);
    if (readLen == SocketConduit.Eof)
      return false;
    else if (readLen == 0)
      return true;
    .....
  }



If it's all the same, I'd prefer to support it like this:

Code:
  protected bool doRead()
  {
    int readLen;

    myConduit.setTimeout(200);
    readLen=myConduit.read(myReadBuffer);
    if (readLen == SocketConduit.Eof)
        return myConduit.hadTimeout;
    .....
  }


... which is checked in, and will be included in the next release. BTW; one of the pleasant things about D is that you can replace this:

Code:
    if (readLen == SocketConduit.Eof)

... with this:

Code:
    if (readLen == myConduit.Eof)

I always find the latter to be more readable, for some reason or other.
Back to top
View user's profile Send private message
RedShodan



Joined: 04 Dec 2004
Posts: 5
Location: Colorado, US

PostPosted: Tue Jan 11, 2005 7:37 pm    Post subject: Reply with quote

hadTimeout is perfectly fine with me. A little more verbose, which is a good thing for maintanence.

Oh and about the instance versus namespace. I personaly prefer using the name space for non-member stuff. It reinforces where its used that this is not an instance variable, but something global to that name space.

Thanks!
Back to top
View user's profile Send private message
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Tue Jan 11, 2005 8:01 pm    Post subject: Reply with quote

RedShodan wrote:
hadTimeout is perfectly fine with me. A little more verbose, which is a good thing for maintanence.
...
Thanks!

Sure! And thanks for bringing this up;
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> Mango All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group