class Timer

Timer handler, manage multiple Action objects, calling them when required. When the Timer is constructed, a new Thread is created to manage timed delays and run Actions.

XXX: there is no way to stop the timer currently. I’m keeping it this way to weed out old Timer implementation legacy in rbot code. -jsn.

Public Class Methods

new() click to toggle source

creates a new Timer and starts it.

# File lib/rbot/timer.rb, line 123
def initialize
  self.extend(MonitorMixin)
  @tick = self.new_cond
  @thread = nil
  @actions = Hash.new
  @current = nil
  self.start
end

Public Instance Methods

add(period, opts = {}, &block) click to toggle source

Creates and installs a new Action, repeatable by default.

period

Action period

opts

options for Action#new, see there

block

Action callback code

Returns the id of the created Action

# File lib/rbot/timer.rb, line 138
def add(period, opts = {}, &block)
  a = Action.new({:repeat => true, :period => period}.merge(opts), &block)
  self.synchronize do
    @actions[a.object_id] = a
    @tick.signal
  end
  return a.object_id
end
add_once(period, opts = {}, &block) click to toggle source

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

# File lib/rbot/timer.rb, line 153
def add_once(period, opts = {}, &block)
  self.add(period, {:repeat => false}.merge(opts), &block)
end
block(aid) click to toggle source

blocks an existing Action

aid

Action id, obtained previously from add() or #add_once()

# File lib/rbot/timer.rb, line 159
def block(aid)
  debug "blocking #{aid}"
  self.synchronize { self[aid].block }
end
configure(aid, opts = {}, &block) click to toggle source

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

# File lib/rbot/timer.rb, line 188
def configure(aid, opts = {}, &block)
  self.synchronize do
    self[aid].configure(opts, &block)
    @tick.signal
  end
end
delete(aid) click to toggle source
Alias for: remove
remove(aid) click to toggle source

removes an existing blocked Action

aid

Action id, obtained previously from add() or #add_once()

# File lib/rbot/timer.rb, line 176
def remove(aid)
  self.synchronize do
    @actions.delete(aid) # or raise "nonexistent action #{aid}"
  end
end
Also aliased as: delete
reschedule(aid, period, &block) click to toggle source

changes Action period

aid

Action id

period

new period

block

(optional) new Action callback code

# File lib/rbot/timer.rb, line 199
def reschedule(aid, period, &block)
  self.configure(aid, :period => period, &block)
end
start() click to toggle source
# File lib/rbot/timer.rb, line 203
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) }
    end
  end
end
stop() click to toggle source
# File lib/rbot/timer.rb, line 216
def stop
  raise 'already stopped' unless @thread
  debug "stopping timer #{self}..."
  @stopping = true
  self.synchronize { @tick.signal }
  @thread.join(60) or @thread.kill
  debug "timer #{self} stopped"
  @thread = nil
end
unblock(aid) click to toggle source

unblocks an existing blocked Action

aid

Action id, obtained previously from add() or #add_once()

# File lib/rbot/timer.rb, line 166
def unblock(aid)
  debug "unblocking #{aid}"
  self.synchronize do
    self[aid].unblock
    @tick.signal
  end
end

Protected Instance Methods

[](aid) click to toggle source
# File lib/rbot/timer.rb, line 228
def [](aid)
  aid ||= @current
  raise "no current action" unless aid
  raise "nonexistent action #{aid}" unless @actions.include? aid
  @actions[aid]
end
run_actions(now = Time.now) click to toggle source
# File lib/rbot/timer.rb, line 235
def run_actions(now = Time.now)
  @actions.keys.each do |k|
    return -1 if @stopping
    a = @actions[k] or next
    next if a.blocked? || a.next > now

    begin
      @current = k
      a.run(now)
    ensure
      @current = nil
    end

    @actions.delete k unless a.next
  end

  nxt = @actions.values.find_all { |v| !v.blocked? }.map{ |v| v.next }.min

  if nxt
    delta = nxt - now
    delta = 0 if delta < 0
    return delta
  else
    return nil
  end
end