Class: NIO::Selector
- Inherits:
-
Object
- Object
- NIO::Selector
- Defined in:
- lib/nio/selector.rb,
lib/nio/jruby/selector.rb,
ext/nio4r/selector.c
Overview
Selectors monitor IO objects for events of interest
Class Method Summary collapse
-
.iops2sym(interest_ops) ⇒ Object
Convert Java NIO interest ops to the corresponding Ruby symbols.
-
.sym2iops(interest, channel) ⇒ Object
Convert nio4r interest symbols to Java NIO interest ops.
Instance Method Summary collapse
-
#close ⇒ Object
Close this selector.
-
#closed? ⇒ Boolean
Is this selector closed?.
-
#deregister(io) ⇒ Object
Deregister the given IO object from the selector.
-
#initialize ⇒ Object
constructor
Methods.
-
#register(io, interest) ⇒ Object
Register interest in an IO object with the selector for the given types of events.
-
#registered?(io) ⇒ Boolean
Is the given IO object registered with the selector?.
-
#select(timeout = nil) ⇒ Object
Select which monitors are ready.
-
#select_each(timeout = nil) ⇒ Object
Iterate across all selectable monitors.
-
#wakeup ⇒ Object
Wake up the other thread that’s currently blocking on this selector.
Constructor Details
#initialize ⇒ Object
Methods
5 6 7 8 9 10 11 12 |
# File 'lib/nio/selector.rb', line 5 def initialize @selectables = {} @lock = Mutex.new # Other threads can wake up a selector @wakeup, @waker = IO.pipe @closed = false end |
Class Method Details
.iops2sym(interest_ops) ⇒ Object
Convert Java NIO interest ops to the corresponding Ruby symbols
29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/nio/jruby/selector.rb', line 29 def self.iops2sym(interest_ops) case interest_ops when SelectionKey::OP_READ, SelectionKey::OP_ACCEPT :r when SelectionKey::OP_WRITE, SelectionKey::OP_CONNECT :w when SelectionKey::OP_READ | SelectionKey::OP_WRITE :rw when 0 then nil else raise ArgumentError, "unknown interest op combination: 0x#{interest_ops.to_s(16)}" end end |
.sym2iops(interest, channel) ⇒ Object
Convert nio4r interest symbols to Java NIO interest ops
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/nio/jruby/selector.rb', line 8 def self.sym2iops(interest, channel) case interest when :r if channel.validOps & SelectionKey::OP_ACCEPT != 0 SelectionKey::OP_ACCEPT else SelectionKey::OP_READ end when :w if channel.respond_to? :connected? and not channel.connected? SelectionKey::OP_CONNECT else SelectionKey::OP_WRITE end when :rw super(:r, channel) | super(:w, channel) else raise ArgumentError, "invalid interest type: #{interest}" end end |
Instance Method Details
#close ⇒ Object
Close this selector
109 110 111 112 113 114 115 116 117 |
# File 'lib/nio/selector.rb', line 109 def close @lock.synchronize do return if @closed @wakeup.close rescue nil @waker.close rescue nil @closed = true end end |
#closed? ⇒ Boolean
Is this selector closed?
120 |
# File 'lib/nio/selector.rb', line 120 def closed?; @closed end |
#deregister(io) ⇒ Object
Deregister the given IO object from the selector
31 32 33 34 35 36 37 |
# File 'lib/nio/selector.rb', line 31 def deregister(io) @lock.synchronize do monitor = @selectables.delete io monitor.close if monitor monitor end end |
#register(io, interest) ⇒ Object
Register interest in an IO object with the selector for the given types of events. Valid event types for interest are:
-
:r - is the IO readable?
-
:w - is the IO writeable?
-
:rw - is the IO either readable or writeable?
19 20 21 22 23 24 25 26 27 28 |
# File 'lib/nio/selector.rb', line 19 def register(io, interest) @lock.synchronize do raise ArgumentError, "this IO is already registered with the selector" if @selectables[io] monitor = Monitor.new(io, interest) @selectables[io] = monitor monitor end end |
#registered?(io) ⇒ Boolean
Is the given IO object registered with the selector?
40 41 42 |
# File 'lib/nio/selector.rb', line 40 def registered?(io) @lock.synchronize { @selectables.has_key? io } end |
#select(timeout = nil) ⇒ Object
Select which monitors are ready
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/nio/selector.rb', line 45 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 end ready_readers, ready_writers = Kernel.select readers, writers, [], timeout return unless ready_readers # timeout or wakeup results = [] ready_readers.each do |io| if io == @wakeup # Clear all wakeup signals we've received by reading them # Wakeups should have level triggered behavior begin @wakeup.read_nonblock(1024) # Loop until we've drained all incoming events redo rescue Errno::EWOULDBLOCK end return else monitor = @selectables[io] monitor.readiness = :r results << monitor end end ready_readwriters = ready_readers & ready_writers ready_writers = ready_writers - ready_readwriters [[ready_writers, :w], [ready_readwriters, :rw]].each do |ios, readiness| ios.each do |io| monitor = @selectables[io] monitor.readiness = readiness results << monitor end end results end end |
#select_each(timeout = nil) ⇒ Object
Iterate across all selectable monitors
94 95 96 97 98 99 |
# File 'lib/nio/selector.rb', line 94 def select_each(timeout = nil, &block) selected = select(timeout) return unless selected selected.each(&block) selected.size end |
#wakeup ⇒ Object
Wake up the other thread that’s currently blocking on this selector
102 103 104 105 106 |
# File 'lib/nio/selector.rb', line 102 def wakeup # Send the selector a signal in the form of writing data to a pipe @waker << "\0" nil end |