class NIO::Selector
Selectors monitor IO objects for events of interest
def close
def close @lock.synchronize do return if @closed @wakeup.close rescue nil @waker.close rescue nil @closed = true end end
def closed?; @closed end
def closed?; @closed end
def deregister(io)
def deregister(io) @lock.synchronize do monitor = @selectables.delete io monitor.close(false) if monitor and not monitor.closed? monitor end end
def empty?
def empty? @selectables.empty? end
def initialize
def initialize @selectables = {} @lock = Mutex.new # Other threads can wake up a selector @wakeup, @waker = IO.pipe @closed = false end
def register(io, interest)
* :w - is the IO writeable?
* :r - is the IO readable?
of events. Valid event types for interest are:
Register interest in an IO object with the selector for the given types
def register(io, interest) @lock.synchronize do if monitor = @selectables[io] raise ArgumentError, "this IO is already registered with the selector as #{monitor.interests.inspect}" end monitor = Monitor.new(io, interest, self) @selectables[io] = monitor monitor end end
def registered?(io)
def registered?(io) @lock.synchronize { @selectables.has_key? io } end
def select(timeout = nil)
def select(timeout = nil) @lock.synchronize do readers, writers = [@wakeup], [] @selectables.each do |io, monitor| readers << io if monitor.interests == :r || monitor.interests == :rw writers << io if monitor.interests == :w || monitor.interests == :rw monitor.readiness = nil end ready_readers, ready_writers = Kernel.select readers, writers, [], timeout return unless ready_readers # timeout or wakeup selected_monitors = Set.new ready_readers.each do |io| if io == @wakeup # Clear all wakeup signals we've received by reading them # Wakeups should have level triggered behavior @wakeup.read(@wakeup.stat.size) return else monitor = @selectables[io] monitor.readiness = :r selected_monitors << monitor end end ready_writers.each do |io| monitor = @selectables[io] monitor.readiness = case monitor.readiness when :r :rw else :w end selected_monitors << monitor end if block_given? selected_monitors.each do |m| yield m end selected_monitors.size else selected_monitors end end end
def wakeup
has the same effect as invoking it just once. In other words, it provides
Invoking this method more than once between two successive select calls
any such thread exists.
Wake up a thread that's in the middle of selecting on this selector, if
def wakeup # Send the selector a signal in the form of writing data to a pipe @waker.write "\0" nil end