Class: DTC::Utils::MiniSelect
- Inherits:
-
Object
- Object
- DTC::Utils::MiniSelect
- Defined in:
- lib/dtc/utils/mini_select.rb
Overview
Small select(2) implementation
Constant Summary collapse
- BUFSIZE =
4096
Instance Attribute Summary collapse
-
#shutdown ⇒ Object
readonly
Returns the value of attribute shutdown.
-
#stop_when_empty ⇒ Object
Default: True.
Class Method Summary collapse
-
.run(*args, &block) ⇒ Object
self.new(&block).run(*args).
Instance Method Summary collapse
-
#add_read(fd, &cb) ⇒ Object
Add a file to monitor for reading.
-
#close(fd, &cb) ⇒ Object
Write to specified fd in a non-blocking manner.
-
#close_now(fd, error = nil) ⇒ Object
Close the specified file, calling all callbacks as required, closing the descriptor, and removing them from the miniselect.
-
#empty? ⇒ Boolean
True if no items will be read or written (which also terminates the loop).
-
#every_beat(&block) ⇒ Object
Provided block is called at every select(2) timeout or operation.
-
#every_error(&block) ⇒ Object
Provided block is called at every read/write error.
-
#every_timeout(&block) ⇒ Object
Provided block is called at every select(2) timeout.
-
#initialize {|_self| ... } ⇒ MiniSelect
constructor
:yields: miniselect.
-
#run(timeout = 5) ⇒ Object
Run the select loop, return when it terminates.
-
#stop ⇒ Object
Shutdown the loop after this step.
-
#write(fd, data, &cb) ⇒ Object
Write to specified fd in a non-blocking manner.
Constructor Details
#initialize {|_self| ... } ⇒ MiniSelect
:yields: miniselect
6 7 8 9 10 11 12 13 |
# File 'lib/dtc/utils/mini_select.rb', line 6 def initialize &block # :yields: miniselect @want_read = {} @want_write = {} @want_close = {} @shutdown = false @stop_when_empty = true yield self if block_given? end |
Instance Attribute Details
#shutdown ⇒ Object (readonly)
Returns the value of attribute shutdown.
14 15 16 |
# File 'lib/dtc/utils/mini_select.rb', line 14 def shutdown @shutdown end |
#stop_when_empty ⇒ Object
Default: True. Stops as soon as there are no more watched fds.
16 17 18 |
# File 'lib/dtc/utils/mini_select.rb', line 16 def stop_when_empty @stop_when_empty end |
Class Method Details
.run(*args, &block) ⇒ Object
self.new(&block).run(*args)
82 83 84 |
# File 'lib/dtc/utils/mini_select.rb', line 82 def self.run *args, &block self.new(&block).run(*args) end |
Instance Method Details
#add_read(fd, &cb) ⇒ Object
Add a file to monitor for reading. When read events occur, provided block is yielded with event :read, upon close it is yielded with event :close
28 29 30 |
# File 'lib/dtc/utils/mini_select.rb', line 28 def add_read fd, &cb # :yields: miniselect, event, file, data_string @want_read[fd] = cb end |
#close(fd, &cb) ⇒ Object
Write to specified fd in a non-blocking manner
When write is completed, the file is closed and the provided block is yielded with event :close.
68 69 70 71 72 73 74 |
# File 'lib/dtc/utils/mini_select.rb', line 68 def close fd, &cb # :yields: miniselect, event, file return if fd.closed? @want_close[fd] = cb if Array(@want_read[fd]).empty? && Array(@want_write[fd]).empty? close_now fd end end |
#close_now(fd, error = nil) ⇒ Object
Close the specified file, calling all callbacks as required, closing the descriptor, and removing them from the miniselect
54 55 56 57 58 59 60 61 62 63 |
# File 'lib/dtc/utils/mini_select.rb', line 54 def close_now fd, error = nil event_id = error ? :error : :close Array(@want_read.delete(fd)).each { |cb| cb.call(self, event_id, fd, error) if cb } Array(@want_write.delete(fd)).each { |data, cb| cb.call(self, event_id, fd, error) if cb } Array(@want_close.delete(fd)).each { |cb| cb.call(self, event_id, fd, error) } fd.close unless fd.closed? if error && @error_handlers Array(@error_handlers).each { |cb| cb.call(self, fd, error) } end end |
#empty? ⇒ Boolean
True if no items will be read or written (which also terminates the loop)
22 23 24 |
# File 'lib/dtc/utils/mini_select.rb', line 22 def empty? @want_read.empty? && @want_write.empty? end |
#every_beat(&block) ⇒ Object
Provided block is called at every select(2) timeout or operation
41 42 43 |
# File 'lib/dtc/utils/mini_select.rb', line 41 def every_beat &block # :yields: miniselect (@block ||= []) << block end |
#every_error(&block) ⇒ Object
Provided block is called at every read/write error
49 50 51 |
# File 'lib/dtc/utils/mini_select.rb', line 49 def every_error &block # :yields: miniselect, fd, error (@error_handlers ||= []) << block end |
#every_timeout(&block) ⇒ Object
Provided block is called at every select(2) timeout
45 46 47 |
# File 'lib/dtc/utils/mini_select.rb', line 45 def every_timeout &block # :yields: miniselect (@timeouts ||= []) << block end |
#run(timeout = 5) ⇒ Object
Run the select loop, return when it terminates
76 77 78 79 80 |
# File 'lib/dtc/utils/mini_select.rb', line 76 def run timeout = 5 while !@shutdown && run_select(timeout) Array(@block).each { |cb| cb.call(self) } if @block end end |
#stop ⇒ Object
Shutdown the loop after this step
18 19 20 |
# File 'lib/dtc/utils/mini_select.rb', line 18 def stop @shutdown = :requested_by_stop end |
#write(fd, data, &cb) ⇒ Object
Write to specified fd in a non-blocking manner
When write is completed, provided block is yielded with event :done, upon close it is yielded with event :close
35 36 37 38 39 |
# File 'lib/dtc/utils/mini_select.rb', line 35 def write fd, data, &cb # :yields: miniselect, event, file raise "Cannot write, FD is closed" if fd.closed? raise "Cannot write, FD is marked to close when finished" if @want_close[fd] (@want_write[fd] ||= []) << [data, cb] end |