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, :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
50 @timer = Thread.new do
53 # get the current time
56 # iterate over each event and trigger any that are due
60 @events.each do |event|
62 # trigger the event and mark it for removal
66 # events are ordered, so we can bail on first miss
71 # remove all triggered events
72 triggered.each do |event|
73 @conditions.delete(event.condition)
78 message = format("Unhandled exception (%s): %s\n%s",
79 e.class, e.message, e.backtrace.join("\n"))
80 applog(nil, :fatal, message)
82 # sleep until next check
89 # Create and register a new TimerEvent
90 # +condition+ is the Condition
91 # +delay+ is the number of seconds to delay (default: interval defined in condition)
94 def schedule(condition, delay = condition.interval)
96 unless @conditions.include?(condition)
97 @events << TimerEvent.new(condition, delay)
98 @conditions << condition
99 @events.sort! { |x, y| x.at <=> y.at }
104 # Remove any TimerEvents for the given condition
105 # +condition+ is the Condition
108 def unschedule(condition)
109 @mutex.synchronize do
110 @conditions.delete(condition)
111 @events.reject! { |x| x.condition == condition }
115 # Trigger the event's condition to be evaluated
116 # +event+ is the TimerEvent to trigger
120 Hub.trigger(event.condition, event.phase)
123 # Join the timer thread