easy_timers 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: