-
- # you can call this when you know you're idle, or you can split off a
- # thread and call the run() method to do it for you.
- def tick
- if(@lasttime != 0)
- diff = (Time.now - @lasttime).to_f
- @lasttime = Time.now
- @timers.compact.each { |timer|
- timer.in = timer.in - diff
- }
- @timers.compact.each { |timer|
- if (!timer.blocked)
- if(timer.in <= 0)
- if(timer.run)
- # run once
- @timers.delete(timer)
- end
- end
- end
- }
- else
- # don't do anything on the first tick
- @lasttime = Time.now
+ return a.object_id
+ end
+
+ # Creates and installs a new Action, one-time by default.
+ # _period_:: Action delay
+ # _opts_:: options for Action#new, see there
+ # _block_:: Action callback code
+ #
+ # Returns the id of the created Action
+ def add_once(period, opts = {}, &block)
+ self.add(period, {:repeat => false}.merge(opts), &block)
+ end
+
+ # blocks an existing Action
+ # _aid_:: Action id, obtained previously from add() or add_once()
+ def block(aid)
+ debug "blocking #{aid}"
+ self.synchronize { self[aid].block }
+ end
+
+ # unblocks an existing blocked Action
+ # _aid_:: Action id, obtained previously from add() or add_once()
+ def unblock(aid)
+ debug "unblocking #{aid}"
+ self.synchronize do
+ self[aid].unblock
+ @tick.signal
+ end
+ end
+
+ # removes an existing blocked Action
+ # _aid_:: Action id, obtained previously from add() or add_once()
+ def remove(aid)
+ self.synchronize do
+ @actions.delete(aid) # or raise "nonexistent action #{aid}"
+ end
+ end
+
+ alias :delete :remove
+
+ # Provides for on-the-fly reconfiguration of Actions
+ # _aid_:: Action id, obtained previously from add() or add_once()
+ # _opts_:: see Action#new
+ # _block_:: (optional) new Action callback code
+ def configure(aid, opts = {}, &block)
+ self.synchronize do
+ self[aid].configure(opts, &block)
+ @tick.signal
+ end
+ end
+
+ # changes Action period
+ # _aid_:: Action id
+ # _period_:: new period
+ # _block_:: (optional) new Action callback code
+ def reschedule(aid, period, &block)
+ self.configure(aid, :period => period, &block)
+ end
+
+ def start
+ raise 'already started' if @thread
+ @stopping = false
+ debug "starting timer #{self}"
+ @thread = Thread.new do
+ loop do
+ tmout = self.run_actions
+ break if tmout and tmout < 0
+ self.synchronize { @tick.wait(tmout) }