RnD-Soft/main_loop

View on GitHub
lib/main_loop/bus.rb

Summary

Maintainability
A
35 mins
Test Coverage
A
100%
require 'monitor'
require 'timeouter'

module MainLoop
  class Bus

    include MonitorMixin

    attr_reader :read, :write

    EOL = "\n".freeze

    def initialize
      super()
      @read, @write = IO.pipe
      @read.sync = true
      @write.sync = true
      @buffer = ''
    end

    def empty?(timeout = 0)
      !wait_for_event(timeout)
    end

    def close
      @write.close rescue nil
      @read.close rescue nil
    end

    def closed?
      @write.closed? || @read.closed?
    end

    def puts(str)
      synchronize do
        @write.puts str.to_s
      end
    end

    def wait_for_event(timeout)
      IO.select([@read], [], [], timeout)
    end

    def gets(timeout)
      Timeouter.loop(timeout) do |t|
        line = gets_nonblock if wait_for_event(t.left)
        return line if line
      end
    end

    def gets_nonblock
      while (ch = @read.read_nonblock(1))
        @buffer << ch
        next if ch != MainLoop::Bus::EOL

        line = @buffer
        @buffer = ''
        return line&.strip
      end
      nil
    rescue IO::WaitReadable
      nil
    end

  end
end