Class: DTC::Utils::MiniSelect

Inherits:
Object
  • Object
show all
Defined in:
lib/dtc/utils/mini_select.rb

Overview

Small select(2) implementation

Constant Summary collapse

BUFSIZE =
4096

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize {|_self| ... } ⇒ MiniSelect

:yields: miniselect

Yields:

  • (_self)

Yield Parameters:



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

#shutdownObject (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_emptyObject

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)

Returns:

  • (Boolean)


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

#stopObject

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