lib/fusuma/plugin/inputs/timer_input.rb in fusuma-2.5.1 vs lib/fusuma/plugin/inputs/timer_input.rb in fusuma-3.0.0

- old
+ new

@@ -1,62 +1,77 @@ # frozen_string_literal: true require_relative "./input" +require "timeout" module Fusuma module Plugin module Inputs # libinput commands wrapper class TimerInput < Input - DEFAULT_INTERVAL = 0.3 + include Singleton + DEFAULT_INTERVAL = 5 + EPSILON_TIME = 0.02 def config_param_types { interval: [Float] } end - attr_reader :pid + def initialize(*args, interval: nil) + super(*args) + @interval = interval || config_params(:interval) || DEFAULT_INTERVAL + @early_wake_queue = Queue.new + end + attr_reader :pid, :interval + def io @io ||= begin reader, writer = create_io @pid = start(reader, writer) reader end end def start(reader, writer) - pid = fork do - timer_loop(reader, writer) + Thread.new do + timer_loop(writer) end - Process.detach(pid) - writer.close - pid + nil end - def timer_loop(reader, writer) - reader.close - begin - loop do - sleep interval - writer.puts "timer" + def timer_loop(writer) + delta_t = @interval + next_wake = Time.now + delta_t + loop do + sleep_time = next_wake - Time.now + if sleep_time <= 0 + raise Timeout::Error end - rescue Errno::EPIPE - exit 0 - rescue => e - MultiLogger.error e + + Timeout.timeout(sleep_time) do + next_wake = [@early_wake_queue.deq, next_wake].min + end + rescue Timeout::Error + writer.puts "timer" + next_wake = Time.now + delta_t end + rescue Errno::EPIPE + exit 0 + rescue => e + MultiLogger.error e end + def wake_early(t) + @early_wake_queue.push(t + EPSILON_TIME) + end + private def create_io IO.pipe - end - - def interval - config_params(:interval) || DEFAULT_INTERVAL end end end end end