lib/main_loop/bus.rb
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