Class: Nodule::LineIO

Inherits:
Base
  • Object
show all
Defined in:
lib/nodule/line_io.rb

Instance Attribute Summary

Attributes inherited from Base

#prefix, #read_count, #readers, #running, #topology

Instance Method Summary collapse

Methods inherited from Base

#add_reader, #add_readers, #clear!, #done?, #join_topology!, #output, #output!, #output?, #read_until, #require_read_count, #run_readers, #stop, #stop!, #verbose, #wait, #wait_with_backoff

Constructor Details

#initialize(opts = {}) ⇒ LineIO

A few extra bits to help with handling IO objects (files, pipes, etc.), like setting up a background thread to select() and read lines from it and call run_readers.

r, w = IO.pipe nio = Nodule::Stdio.new :io => r, :run => true

Parameters:

  • opts (Hash{Symbol => IO,Symbol,Proc}) (defaults to: {})

Options Hash (opts):

  • :io (IO)

    required IO object, pipes & files should work fine



16
17
18
19
20
21
22
# File 'lib/nodule/line_io.rb', line 16

def initialize(opts={})
  @running = false
  raise ArgumentError.new ":io is required and must be a descendent of IO" unless opts[:io].kind_of?(IO)
  @io = opts.delete(:io)

  super(opts)
end

Instance Method Details

simply calls print *args on the io handle

Parameters:

  • see (String)

    IO.print



62
63
64
# File 'lib/nodule/line_io.rb', line 62

def print(*args)
  @io.print(*args)
end

#puts(*args) ⇒ Object

calls io.puts *args

Parameters:

  • see (String)

    IO.print



70
71
72
# File 'lib/nodule/line_io.rb', line 70

def puts(*args)
  @io.puts(*args)
end

#runObject

Create a background thread to read from IO and call Nodule run_readers.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/nodule/line_io.rb', line 27

def run
  super

  Thread.new do
    begin
      @running = true # relies on the GIL
      while @running do
        ready = IO.select([@io], [], [], 0.2)
        unless ready.nil?
          line = @io.readline
          run_readers(line, self)
        end
      end

      # run may be over, but read the rest of the data up to EOF anyways
      @io.foreach do |line|
        run_readers(line, self)
      end
    rescue EOFError
      verbose "EOFError: #{@io} probably closed."
      @io.close
      Thread.current.exit
    rescue Exception => e
      STDERR.print "Exception in #{name} IO thread: #{e.inspect}\n"
      abort e
    end
  end

  wait_with_backoff 30 do @running end
end