From: Paul Brannan Date: 2001-12-14T00:14:53+09:00 Subject: [ruby-talk:28415] Re: [RCR] IO.select should return array for timeout. On Thu, Dec 13, 2001 at 04:03:14PM +0900, Yukihiro Matsumoto wrote: > But now I think it's arguable. If IO.select returned [[],[],[]] for > timeout, most routines could handle timeout well. I'm still not sure, > so I put this as an RCR to call for discussion. How would you propose that a select() loop look? Currently, I write something like this: loop do if (fds = select([fd1], [fd2, fd3], nil, 10)) then for fd in fds[0] # Handle read fds end for fd in fds[1] # Handle write fds end else # Timeout end end whereas with the new solution, I would have to do: loop do fds = select([fd1], [fd2, fd3], nil, 10) if fds[0].size == 0 and fds[1].size == 0 and fds[2].size == 0 then # Timeout else for fd in fds[0] # Handle read fds end for fd in fds[1] # Handle write fds end end end Note the extra test for size on all three sub-arrays. I suppose I could use the test: if fds[0].join.size == 0 then # Timeout else # ... end But this is not entirely clear, and is probably even slower. Contrast this with a C example (just for kicks): for(;;) { FD_ZERO(&r_fds); FD_SET(fd1, &r_fds); FD_ZERO(&w_fds); FD_SET(fd2, &w_fds); FD_SET(fd3, &w_fds); tv.tv_sec = 10; tv.tv_usec = 0; retval = select( ((fd1 > fd2) ? MAX(fd1, fd3) : MAX(fd2, fd3)), &r_fds, &w_fds, NULL, &tv); if(retval > 0) { if(FD_ISSET(fd1, &r_fds)) { /* Do something */ } if(FD_ISSET(fd2, &w_fds)) { /* Do something */ } if(FD_ISSET(fd3, &w_fds)) { /* Do something */ } } else if(retval == 0) { /* Timeout */ } else { /* Error */ } } In C, I check for timeout by checking the return value of select(), and I check each fd to see if it is ready (I know no portable way to iterate over the fds in the set without using a wrapper, like ACE). So currently Ruby is mostly consistent with C for timeout, and more convenient than C for checking if fds are ready. I like the way it is. Also, why not post this RCR on the Rubygarden? Paul