easy_timers 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ /.idea/
16
+ /.idea
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - jruby-18mode
6
+ - jruby-19mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in easy_timers.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # EasyTimers
2
+
3
+ [![Build Status](https://travis-ci.org/malakai97/easy_timers.svg?branch=master)](https://travis-ci.org/malakai97/easy_timers)
4
+
5
+ A simple interface for creating timers with callbacks that handles all the threading for you.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'easy_timers'
13
+ ```
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install easy_timers
18
+
19
+ ## Usage
20
+
21
+ Create a new group of timers with `EasyTimers::Timers.new`:
22
+
23
+ ```ruby
24
+ require 'easy_timers'
25
+
26
+ timers = EasyTimers::Timers.new
27
+ ```
28
+
29
+ Schedule a timer to execute 10 seconds from now with `EasyTimers::Timers#after`:
30
+
31
+ ```ruby
32
+ timers.after(10) { puts "Hello world" }
33
+ ```
34
+
35
+ Now `timers` has a single timer that will call its block in ten seconds.
36
+
37
+ You can also supply a ruby Time object instead of an interval.
38
+
39
+ ```ruby
40
+ the_future = Time.now + 10
41
+ timers.after(the_future) { put "Ten seconds have passed." }
42
+ ```
43
+
44
+ If you want to be able to cancel a specific timer, you should give it a name:
45
+
46
+ ```ruby
47
+ timers.after(60, :one_minute) { puts "It's been 60 seconds." }
48
+ # do some work and decide to change our mind
49
+ timers.cancel(:one_minute)
50
+ ```
51
+
52
+ If you'd rather not mint your own names, one will be generated for you:
53
+
54
+ ```ruby
55
+ timer_name = timers.after(10) { puts "hai" }
56
+ timers.cancel(timer_name)
57
+ ```
58
+
59
+ You can also create periodic timers with `EasyTimers::Timers#every`:
60
+
61
+ ```ruby
62
+ timer_name = timers.every(1) { puts "One second has passed." }
63
+ ```
64
+
65
+ Periodic timers will be scheduled repeatedly until cancelled.
66
+
67
+ Need a combination of the above? You can schedule a period timer to start at
68
+ a certain time, then scheduled repeatedly using a different interval:
69
+
70
+ ```ruby
71
+ timer_name = timers.after_then_every(0.5, 0.1, :my_timer) { puts "tic toc" }
72
+ ```
73
+
74
+ The above timer will first fire after half a second, then fire every 0.1 seconds thereafter.
75
+
76
+ ## Contributing
77
+
78
+ 1. Fork it ( https://github.com/malakai97/easy_timers/fork )
79
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
80
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
81
+ 4. Push to the branch (`git push origin my-new-feature`)
82
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
7
+ task :test => :spec
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ require File.expand_path('../lib/easy_timers/version', __FILE__)
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "easy_timers"
6
+ spec.version = EasyTimers::VERSION
7
+ spec.authors = ["Bryan Hockey"]
8
+ spec.email = ["bryan.hockey@peimhal.com"]
9
+ spec.summary = %q{Easily create and manage asynchronous timers using dates or durations.}
10
+ spec.description = %q{Easily create and manage asynchronous timers using dates or durations.}
11
+ spec.homepage = "http://github.com/malakai97/easy_timers"
12
+ spec.license = "MIT"
13
+
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.6"
20
+ spec.add_development_dependency "rake"
21
+ spec.add_development_dependency "rspec"
22
+ end
@@ -0,0 +1,94 @@
1
+ require 'easy_timers/timer'
2
+
3
+ module EasyTimers
4
+
5
+ # Maintains a list of timers.
6
+ class Group
7
+
8
+ GRANULARITY = 1000 # milliseconds
9
+
10
+ # Create a new instance and begin the loop
11
+ def initialize
12
+ @events = [] # Maintained in sorted order of furthest-soonest, aka descending order.
13
+ @names = Hash.new do |hash,key| # Each array in descending order.
14
+ hash[key] = []
15
+ end
16
+ @looping_thread = Thread.new() do
17
+ while true
18
+ self.loop()
19
+ end
20
+ end
21
+ end
22
+
23
+
24
+ # Insert a new timer into the group
25
+ # @param timer [Timer]
26
+ def insert(timer)
27
+ index = @events.index do |element|
28
+ timer.time > element.time
29
+ end
30
+
31
+ if index == nil
32
+ @events.push(timer)
33
+ else
34
+ @events.insert(index, timer)
35
+ end
36
+
37
+ @names[timer.name].push(timer)
38
+ @looping_thread.run()
39
+ return timer.name
40
+ end
41
+
42
+
43
+ # Delete a timer from the group.
44
+ # @param name [Symbol]
45
+ def delete(name)
46
+ if @names[name].size() > 0
47
+ @names[name].each do |timer|
48
+ timer.cancel()
49
+ end
50
+ @names.delete(name)
51
+ @looping_thread.run()
52
+ end
53
+ end
54
+
55
+
56
+ # Perform a single loop.
57
+ def loop()
58
+ if @events.empty?
59
+ sleep #until woken
60
+ else
61
+ time = self.get_current_time()
62
+
63
+ while @events.last.time <= time
64
+ timer = @events.pop
65
+ @names[timer.name].pop
66
+ if timer.cancelled? == false
67
+ if timer.recurring == true
68
+ newTime = timer.time + timer.interval
69
+ newTimer = Timer.new(newTime, timer.name, timer.interval, timer.recurring, timer.callback)
70
+ self.insert(newTimer)
71
+ end
72
+ Thread.new do
73
+ timer.callback.call
74
+ end
75
+ end
76
+ end
77
+
78
+ untilNext = @events.last.time - time
79
+ if untilNext < 0.0
80
+ untilNext = 0.0
81
+ end
82
+ sleep untilNext
83
+ end
84
+ end
85
+
86
+
87
+ # Return the current time in seconds
88
+ def get_current_time()
89
+ return Time.now.gmtime.to_f
90
+ end
91
+
92
+
93
+ end
94
+ end
@@ -0,0 +1,43 @@
1
+ require 'time'
2
+
3
+ module EasyTimers
4
+
5
+ # Wraps a timer
6
+ class Timer
7
+ attr_reader :time, :name, :interval, :recurring, :callback
8
+
9
+ # Create a new instance
10
+ # @param time [Float] Seconds since epoch.
11
+ # @param name [Symbol] A name for this timer; generated from the current clock time if nil.
12
+ # @param interval [Float] Seconds.
13
+ # @param recurring [Boolean]
14
+ # @param callback [Callable]
15
+ def initialize(time, name, interval, recurring, callback)
16
+ @time = time
17
+ @name = name
18
+ @interval = interval
19
+ @recurring = recurring
20
+ @callback = callback
21
+ @cancelled = false
22
+
23
+ if @name == nil
24
+ @name = Time.now.gmtime.to_f.to_s.to_sym
25
+ end
26
+ end
27
+
28
+
29
+ # Cancel the timer by overwriting the callback
30
+ def cancel()
31
+ @callback = nil
32
+ @cancelled = true
33
+ end
34
+
35
+
36
+ # Check if this timer has been cancelled.
37
+ def cancelled?
38
+ return @cancelled
39
+ end
40
+
41
+ end
42
+ end
43
+
@@ -0,0 +1,98 @@
1
+ require 'easy_timers/timer'
2
+ require 'easy_timers/group'
3
+ require 'time'
4
+
5
+ module EasyTimers
6
+ class Timers
7
+
8
+ # Create a new Timers instance to hold our timers.
9
+ # @return [Timers]
10
+ def initialize()
11
+ @group = Group.new()
12
+ end
13
+
14
+
15
+ # @overload after(time, name = nil, &block)
16
+ # Schedule a block to be called immediately after the specified time.
17
+ # @param time [Time] A time to fire the callback.
18
+ # @param name [Symbol] An optional name for the timer.
19
+ # Will be generated if not provided.
20
+ # @return [Symbol] The name of the timer.
21
+ # @overload after(seconds, name = nil, &block)
22
+ # Schedule a block to be called after the given number of seconds.
23
+ # @param seconds [Float] Number of seconds to wait before firing the callback.
24
+ # @param name [Symbol] An optional name for the timer.
25
+ # Will be generated if not provided.
26
+ # @return [Symbol] The name of the timer.
27
+ def after(time, name = nil, &block)
28
+ if time.is_a?(Time)
29
+ time = time.gmtime.to_f
30
+ elsif time.is_a?(Numeric)
31
+ time = Time.now.gmtime.to_f + time.to_f
32
+ else
33
+ raise ArgumentError, "Invalid arguments to method."
34
+ end
35
+
36
+ timer = Timer.new(time, name, 0, false, block)
37
+ name = @group.insert(timer)
38
+ return name
39
+ end
40
+
41
+
42
+ # Schedule a block to fire every given amount of seconds
43
+ # @param seconds [Float,Fixnum] Number of seconds to wait before firing the callback,
44
+ # and the interval between subsequent events.
45
+ # @param name [Symbol] An optional name for the timer.
46
+ # Will be generated if not provided.
47
+ # @return [Symbol] The name of the timer.
48
+ def every(seconds, name = nil, &block)
49
+ if seconds <= 0 # zero disallowed because you can't run it every 0 seconds.
50
+ raise ArgumentError, "Interval must be greater than 0."
51
+ end
52
+ interval = seconds.to_f
53
+ time = Time.now.gmtime.to_f + interval
54
+ timer = Timer.new(time, name, interval, true, block)
55
+ name = @group.insert(timer)
56
+ return name
57
+ end
58
+
59
+
60
+ # @overload after_then_every(start_date, interval, name = nil, &block)
61
+ # Schedule a recurring timer that will first fire after the given time.
62
+ # @param start_date [Time] A time to first fire the callback
63
+ # @param interval [Float,Fixnum] Number of seconds to delay after the callback returns.
64
+ # @param name [Symbol] An optional name for the timer.
65
+ # Will be generated if not provided.
66
+ # @return [Symbol] The name of the timer.
67
+ # @overload after_then_every(start_seconds, interval, name = nil, &block)
68
+ # Schedule a recurring timer that will first fire after the given time.
69
+ # The timer will then be rescheduled every interval.
70
+ # @param start_seconds [Float,Fixnum] Number of seconds to delay before firing the
71
+ # first callback.
72
+ # @param interval [Float,Fixnum] Number of seconds to delay after the callback returns.
73
+ # @param name [Symbol] An optional name for the timer.
74
+ # Will be generated if not provided.
75
+ # @return [Symbol] The name of the timer.
76
+ def after_then_every(start, interval, name = nil, &block)
77
+
78
+ if start.is_a?(Time) && interval.is_a?(Numeric) && block_given?
79
+ time = start.gmtime.to_f
80
+ elsif start.is_a?(Numeric) && interval.is_a?(Numeric) && block_given?
81
+ time = Time.now.gmtime.to_f + start.to_f
82
+ else
83
+ raise ArgumentError, "Invalid arguments."
84
+ end
85
+
86
+ timer = Timer.new(time, name, interval.to_f, true, block)
87
+ name = @group.insert(timer)
88
+ return name
89
+ end
90
+
91
+
92
+ # Cancel a timer.
93
+ def cancel(name)
94
+ @group.delete(name)
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,3 @@
1
+ module EasyTimers
2
+ VERSION = "1.0.5"
3
+ end
@@ -0,0 +1,5 @@
1
+ require "easy_timers/version"
2
+
3
+ module EasyTimers
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,3 @@
1
+ require 'bundler/setup'
2
+ require 'rspec'
3
+ require 'easy_timers'
@@ -0,0 +1,217 @@
1
+ require 'spec_helper'
2
+ require 'easy_timers/timers'
3
+
4
+ describe EasyTimers::Timers do
5
+
6
+ describe '#after(time, name = nil, &block)' do
7
+ before(:each) do
8
+ @timers = EasyTimers::Timers.new()
9
+ end
10
+
11
+ it 'fires at a future time' do
12
+ x = 1
13
+ time = Time.now + 0.1
14
+ @timers.after(time, :test) { x = 5}
15
+ expect(x).to eq(1)
16
+ sleep 0.12
17
+ expect(x).to eq(5)
18
+ end
19
+
20
+ it 'fires multiple times' do
21
+ x = []
22
+ now = Time.now
23
+ @timers.after(now + 0.6, :a) { x.push(:a) }
24
+ @timers.after(now + 0.5, :b) { x.push(:b) }
25
+ @timers.after(now + 0.4, :c) { x.push(:c) }
26
+ @timers.after(now + 0.3, :d) { x.push(:d) }
27
+ @timers.after(now + 0.2, :e) { x.push(:e) }
28
+ @timers.after(now + 0.1, :f) { x.push(:f) }
29
+ @timers.after(now + 0.25, :g) { x.push(:g) }
30
+ sleep 0.65
31
+ expect(x).to eq([:f, :e, :g, :d, :c, :b, :a])
32
+ end
33
+
34
+ it 'generates a custom name' do
35
+ name = nil
36
+ name = @timers.after(Time.now + 0.1) { true }
37
+ expect(name).to_not eq(nil)
38
+ end
39
+
40
+ it 'fires immediately when given a time in the past' do
41
+ x = 0
42
+ time = Time.now - 1
43
+ @timers.after(time, :test) { x = 5 }
44
+ sleep 0.1
45
+ expect(x).to eq(5)
46
+ end
47
+
48
+ end
49
+
50
+
51
+ describe '#after(seconds, name = nil, &block)' do
52
+ before(:each) do
53
+ @timers = EasyTimers::Timers.new()
54
+ end
55
+
56
+ it 'fires after an interval' do
57
+ x = 1
58
+ @timers.after(0.1, :test) do
59
+ x = 5
60
+ end
61
+ expect(x).to eq(1)
62
+ sleep 0.12
63
+ expect(x).to eq(5)
64
+ end
65
+
66
+ it 'fires multiple times in succession' do
67
+ x = []
68
+ @timers.after(0.6, :a) { x.push(:a) }
69
+ @timers.after(0.5, :b) { x.push(:b) }
70
+ @timers.after(0.4, :c) { x.push(:c) }
71
+ @timers.after(0.3, :d) { x.push(:d) }
72
+ @timers.after(0.2, :e) { x.push(:e) }
73
+ @timers.after(0.1, :f) { x.push(:f) }
74
+ @timers.after(0.25, :g) { x.push(:g) }
75
+ sleep 0.65
76
+ expect(x).to eq([:f, :e, :g, :d, :c, :b, :a])
77
+
78
+ end
79
+
80
+ it 'generates a custom name' do
81
+ name = nil
82
+ name = @timers.after(0.1) { true }
83
+ expect(name).to_not eq(nil)
84
+ end
85
+
86
+ it 'fires immediately when given a time in the past' do
87
+ x = 0
88
+ @timers.after(-1, :test) { x = 5 }
89
+ sleep 0.1
90
+ expect(x).to eq(5)
91
+ end
92
+
93
+ end
94
+
95
+
96
+ describe '#every' do
97
+ before(:each) do
98
+ @timers = EasyTimers::Timers.new()
99
+ end
100
+
101
+ it 'fires more than once' do
102
+ x = 0
103
+ @timers.every(0.2) { x += 1}
104
+ expect(x).to eq(0)
105
+ sleep 0.7
106
+ expect(x).to eq(3)
107
+ end
108
+
109
+ it 'works with a staggered timer' do
110
+ x = []
111
+ @timers.every(0.3) { x.push(:a) }
112
+ sleep 0.1
113
+ @timers.every(0.3) { x.push(:b) }
114
+ sleep 0.7
115
+ expect(x).to eq([:a, :b, :a, :b])
116
+ end
117
+
118
+ it 'works with a similar timer' do
119
+ x = 0
120
+ @timers.every(0.1) { x += 1 }
121
+ @timers.every(0.1) { x += 1 }
122
+ sleep 0.45
123
+ expect(x).to eq(8)
124
+ end
125
+
126
+ it 'generates a custom name' do
127
+ name = nil
128
+ name = @timers.every(0.1) { true }
129
+ expect(name).to_not eq(nil)
130
+ end
131
+
132
+ end
133
+
134
+
135
+ describe '#after_then_every(start_seconds, interval, name = nil, &block)' do
136
+ before(:each) do
137
+ @timers = EasyTimers::Timers.new()
138
+ end
139
+
140
+ it 'fires after seconds then fires again' do
141
+ x = 0
142
+ @timers.after_then_every(0.2, 0.1) { x += 1}
143
+ expect(x).to eq(0)
144
+ sleep 0.25
145
+ expect(x).to eq(1)
146
+ sleep 0.2
147
+ expect(x).to eq(3)
148
+ end
149
+
150
+ it 'works with a staggered timer' do
151
+ x = []
152
+ @timers.after_then_every(0.2, 0.3) { x.push(:a) }
153
+ @timers.after_then_every(0.3, 0.3) { x.push(:b) }
154
+ sleep 0.7
155
+ expect(x).to eq([:a, :b, :a, :b])
156
+ end
157
+
158
+ it 'works with a similar timer' do
159
+ x = 0
160
+ @timers.after_then_every(0.2, 0.4) { x += 1 }
161
+ @timers.after_then_every(0.2, 0.4) { x += 1 }
162
+ sleep 0.8
163
+ expect(x).to eq(4)
164
+ end
165
+
166
+ it 'generates a custom name' do
167
+ name = nil
168
+ name = @timers.after_then_every(0.1, 0.1) { true }
169
+ expect(name).to_not eq(nil)
170
+ end
171
+ end
172
+
173
+
174
+ describe '#cancel' do
175
+ before(:each) do
176
+ @timers = EasyTimers::Timers.new()
177
+ end
178
+
179
+ it 'deletes an #after timer' do
180
+ x = 0
181
+ @timers.after(0.1, :test) { x += 1 }
182
+ @timers.cancel(:test)
183
+ sleep 0.15
184
+ expect(x).to eq(0)
185
+ end
186
+
187
+ it 'deletes an #every timer after it has fired' do
188
+ x = 0
189
+ @timers.every(0.1, :test) { x += 1 }
190
+ sleep 0.25
191
+ @timers.cancel(:test)
192
+ sleep 0.1
193
+ expect(x).to eq(2)
194
+ end
195
+
196
+ it 'fails gracefully if the timer is past' do
197
+ x = 0
198
+ @timers.after(0.1, :test) { x += 1 }
199
+ sleep 0.15
200
+ @timers.cancel(:test)
201
+ end
202
+
203
+ it 'fails gracefully if the timer never existed' do
204
+ @timers.cancel(:fake)
205
+ end
206
+
207
+ it 'works with generated names' do
208
+ x = 0
209
+ name = @timers.after(0.1) { x += 1 }
210
+ @timers.cancel(name)
211
+ sleep 0.15
212
+ expect(x).to eq(0)
213
+ end
214
+ end
215
+
216
+
217
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: easy_timers
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.5
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Bryan Hockey
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-08-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.6'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.6'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Easily create and manage asynchronous timers using dates or durations.
63
+ email:
64
+ - bryan.hockey@peimhal.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .travis.yml
71
+ - Gemfile
72
+ - LICENSE.txt
73
+ - README.md
74
+ - Rakefile
75
+ - easy_timers.gemspec
76
+ - lib/easy_timers.rb
77
+ - lib/easy_timers/group.rb
78
+ - lib/easy_timers/timer.rb
79
+ - lib/easy_timers/timers.rb
80
+ - lib/easy_timers/version.rb
81
+ - spec/spec_helper.rb
82
+ - spec/timers_spec.rb
83
+ homepage: http://github.com/malakai97/easy_timers
84
+ licenses:
85
+ - MIT
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ segments:
97
+ - 0
98
+ hash: -2036513913167786788
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ segments:
106
+ - 0
107
+ hash: -2036513913167786788
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 1.8.23
111
+ signing_key:
112
+ specification_version: 3
113
+ summary: Easily create and manage asynchronous timers using dates or durations.
114
+ test_files:
115
+ - spec/spec_helper.rb
116
+ - spec/timers_spec.rb
117
+ has_rdoc: