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 +16 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +82 -0
- data/Rakefile +7 -0
- data/easy_timers.gemspec +22 -0
- data/lib/easy_timers/group.rb +94 -0
- data/lib/easy_timers/timer.rb +43 -0
- data/lib/easy_timers/timers.rb +98 -0
- data/lib/easy_timers/version.rb +3 -0
- data/lib/easy_timers.rb +5 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/timers_spec.rb +217 -0
- metadata +117 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
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
|
+
[](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
data/easy_timers.gemspec
ADDED
@@ -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
|
data/lib/easy_timers.rb
ADDED
data/spec/spec_helper.rb
ADDED
data/spec/timers_spec.rb
ADDED
@@ -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:
|