Class: ActionTimer::Timer

Inherits:
Object
  • Object
show all
Defined in:
lib/actiontimer/Timer.rb

Instance Method Summary collapse

Constructor Details

#initialize(args = {}, extra = nil) ⇒ Timer

pool

ActionPool for processing actions

Creates a new timer Argument hash: :logger, :auto_start



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/actiontimer/Timer.rb', line 9

def initialize(args={}, extra=nil)
    auto_start = true
    @delta = nil
    if(args.is_a?(Hash))
        @pool = args[:pool] ? args[:pool] : ActionPool::Pool.new
        @logger = args[:logger] && args[:logger].is_a?(Logger) ? args[:logger] : Logger.new(nil)
        auto_start = args.has_key?(:auto_start) ? args[:auto_start] : true
        @delta = args[:delta] ? args[:delta].to_f : nil
    else
        @pool = args.is_a?(ActionPool::Pool) ? args : ActionPool::Pool.new
        @logger = extra && extra.is_a?(Logger) ? extra : Logger.new(nil)
    end
    @actions = []
    @new_actions = []
    @timer_thread = nil
    @stop_timer = false
    @add_lock = Splib::Monitor.new
    @awake_lock = Splib::Monitor.new
    @sleeper = Splib::Monitor.new
    @respond_to = Thread.current
    start if auto_start
end

Instance Method Details

#actionsObject

Actions registered with the timer



162
163
164
# File 'lib/actiontimer/Timer.rb', line 162

def actions
    @actions.dup
end

#add(hash, &func) ⇒ Object

period

amount of time between runs

once

only run this action once

data

data to pass to block

owner

owner of Action

func

block to be executed

Add a new action to block

Raises:

  • (ArgumentError)


48
49
50
51
52
53
54
55
56
57
58
# File 'lib/actiontimer/Timer.rb', line 48

def add(hash, &func)
    raise ArgumentError.new('Expecting hash of arguments') unless hash.is_a?(Hash)
    raise ArgumentError.new('A period must be provided for timed action') unless hash[:period]
    raise ArgumentError.new('Block must be provided') unless block_given?
    raise ArgumentError.new('Block must accept data value') if hash[:data] && func.arity == 0
    args = {:once => false, :data => nil, :owner => nil}.merge(hash)
    action = Action.new(args.merge(:timer => self), &func)
    @add_lock.synchronize{ @new_actions << action }
    wakeup if running?
    action
end

#clear(owner = nil) ⇒ Object

owner

owner actions to remove

Clears timer of actions. If an owner is supplied only actions owned by owner will be removed



140
141
142
143
144
145
146
147
148
# File 'lib/actiontimer/Timer.rb', line 140

def clear(owner=nil)
    if(owner.nil?)
        @actions.clear
        @new_actions.clear
    else
        @actions.each{|a| @actions.delete(a) if a.owner == owner}
    end
    wakeup if running?
end

#pauseObject

Pause the timer in its current state.



116
117
118
119
120
121
122
123
# File 'lib/actiontimer/Timer.rb', line 116

def pause
    @stop_timer = true
    if(running?)
        wakeup
        @timer_thread.join
    end
    @timer_thread = nil
end

#register(action) ⇒ Object

actions

Array of actions or single ActionTimer::Action

Add single or multiple Actions to the timer at once



62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/actiontimer/Timer.rb', line 62

def register(action)
    if(action.is_a?(Array))
        if(action.find{|x|x.is_a?(Action)}.nil?)
            raise ArgumentError.new('Array contains non ActionTimer::Action objects')
        end
    else
        raise ArgumentError.new('Expecting an ActionTimer::Action object') unless action.is_a?(Action)
        action = [action]
    end
    @add_lock.synchronize{ @new_actions = @new_actions + action }
    wakeup if running?
end

#registered?(action) ⇒ Boolean

action

ActionTimer::Action

Is action currently in timer

Returns:

  • (Boolean)


157
158
159
# File 'lib/actiontimer/Timer.rb', line 157

def registered?(action)
    @actions.include?(action)
end

#remove(action) ⇒ Object

action

Action to remove from timer

Remove given action from timer

Raises:

  • (ArgumentError)


77
78
79
80
81
# File 'lib/actiontimer/Timer.rb', line 77

def remove(action)
    raise ArgumentError.new('Expecting an action') unless action.is_a?(Action)
    @actions.delete(action)
    wakeup if running?
end

#running?Boolean

Is timer currently running?

Returns:

  • (Boolean)


151
152
153
# File 'lib/actiontimer/Timer.rb', line 151

def running?
    !@timer_thread.nil?
end

#startObject

Start the timer

Raises:



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/actiontimer/Timer.rb', line 84

def start
    raise AlreadyRunning.new unless @timer_thread.nil?
    @stop_timer = false
    @timer_thread = Thread.new do
        begin
            until @stop_timer do
                to_sleep = get_min_sleep
                if((to_sleep.nil? || to_sleep > 0) && @new_actions.empty?)
                    @awake_lock.unlock if @awake_lock.locked?
                    start = Time.now.to_f
                    to_sleep.nil? ? @sleeper.wait : sleep(to_sleep)
                    actual_sleep = Time.now.to_f - start
                    if(@delta && to_sleep && actual_sleep.within_delta?(:expected => to_sleep, :delta => @delta))
                        actual_sleep = to_sleep
                    end
                    @awake_lock.lock
                else
                    actual_sleep = 0
                end
                tick(actual_sleep)
                add_waiting_actions
            end
        rescue Object => boom
            @timer_thread = nil
            clean_actions
            @logger.fatal("Timer encountered an unexpected error and is shutting down: #{boom}\n#{boom.backtrace.join("\n")}")
            @respond_to.raise boom
        end
    end
end

#stopObject

Stop the timer. Unlike pause, this will completely stop the timer and remove all actions from the timer



127
128
129
130
131
132
133
134
135
# File 'lib/actiontimer/Timer.rb', line 127

def stop
    @stop_timer = true
    if(running?)
        wakeup
        clean_actions
        @timer_thread.join
    end
    @timer_thread = nil
end

#wakeupObject

Forcibly wakes the timer early

Raises:



33
34
35
36
37
38
39
40
# File 'lib/actiontimer/Timer.rb', line 33

def wakeup
    raise NotRunning.new unless running?
    if(@sleeper.waiters > 0)
        @sleeper.signal
    else
        @timer_thread.wakeup if @timer_thread.alive? && @timer_thread.stop?
    end
end