4 attr_accessor :condition, :at, :phase
6 # Instantiate a new TimerEvent that will be triggered after the specified delay
7 # +condition+ is the Condition
8 # +delay+ is the number of seconds from now at which to trigger
11 def initialize(condition, delay)
12 self.condition = condition
13 self.phase = condition.watch.phase
15 now = (Time.now.to_f * 4).round / 4.0
23 attr_reader :events, :pending_events, :conditions, :timer
27 # Get the singleton Timer
34 # Reset the singleton Timer so the next call to Timer.get will
42 # Instantiate a new Timer and start the scheduler loop to handle events
49 @pending_mutex = Mutex.new
51 @timer = Thread.new do
53 # applog(nil, :debug, "timer main loop, #{@events.size} events pending")
56 # pull in pending events
57 @pending_mutex.synchronize do
58 @pending_events.each { |e| @events << e }
62 @events.sort! { |x, y| x.at <=> y.at }
64 # get the current time
67 # iterate over each event and trigger any that are due
70 @events.each do |event|
72 # trigger the event and mark it for removal
76 # events are ordered, so we can bail on first miss
81 # remove all triggered events
82 triggered.each do |event|
83 @conditions.delete(event.condition)
87 message = format("Unhandled exception (%s): %s\n%s",
88 e.class, e.message, e.backtrace.join("\n"))
89 applog(nil, :fatal, message)
91 # sleep until next check
93 # BleakHouseDiagnostic.snapshot
94 # p BleakHouseDiagnostic.logger.mem_usage
101 # Create and register a new TimerEvent
102 # +condition+ is the Condition
103 # +delay+ is the number of seconds to delay (default: interval defined in condition)
106 def schedule(condition, delay = condition.interval)
107 applog(nil, :debug, "timer schedule #{condition} in #{delay} seconds")
108 unless @conditions.include?(condition)
109 @pending_mutex.synchronize do
110 @pending_events << TimerEvent.new(condition, delay)
112 @conditions << condition
116 # Remove any TimerEvents for the given condition
117 # +condition+ is the Condition
120 def unschedule(condition)
121 applog(nil, :debug, "timer unschedule #{condition}")
122 @conditions.delete(condition)
125 # Trigger the event's condition to be evaluated
126 # +event+ is the TimerEvent to trigger
130 applog(nil, :debug, "timer trigger #{event}")
131 Hub.trigger(event.condition, event.phase)
134 # Join the timer thread