When you have to use IO.select, code can get kind of ugly.  Consider
the following code, which determines which connections in the @conns
array are writeable, readable, or have errors.  It then calls the
process method, passing in the flags for read, write, error.

    def tick
      rconns, wconns, econns = select @conns, @conns, @conns, @timeout
      
      @conns.each do |conn|
        read = rconns.include? conn
        write = wconns.include? conn
        error = econns.include? conn

        process conn, read, write, error
      end
    end

     def process conn, read, write, error
       if read
         ...
       end

       if write
         ...
       end

       if error
         ...
       end
    end

This code doesn't seem too neat to me, so I overrode part of IO to
support the use of predicates.  Now one can do:

    def tick
      @conns.each do |conn|
        process conn
      end
    end

    def process conn
       if conn.readable? 
         ...
       end

       if conn.writable?
         ...
       end

       if conn.error?
         ...
       end
    end

To me, this code is a lot neater.  The implementation is below:

    class IO
      attr_accessor :poll_timeout

      def readable?
        res = IO.select [self], nil, nil, @poll_timeout || 0.01
        res and not res[0].nil?
      end
  
      def writable?
        res = IO.select nil, [self], nil, @poll_timeout || 0.01
        res and not res[1].nil?
      end
  
      def error?
        res = IO.select nil, nil, [self], @poll_timeout || 0.01
        res and not res[3].nil?
      end
   end

If people here like this, I'll submit it to rcrchive.  Any thoughts?

Bill