timers 4.1.1 → 4.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.rubocop.yml +28 -0
- data/.ruby-version +1 -0
- data/.travis.yml +13 -10
- data/CHANGES.md +31 -23
- data/Gemfile +16 -3
- data/LICENSE +1 -1
- data/README.md +27 -17
- data/Rakefile +6 -3
- data/lib/timers.rb +4 -3
- data/lib/timers/events.rb +34 -39
- data/lib/timers/group.rb +30 -35
- data/lib/timers/timer.rb +25 -24
- data/lib/timers/version.rb +3 -1
- data/lib/timers/wait.rb +17 -18
- data/spec/spec_helper.rb +5 -3
- data/spec/{cancel_spec.rb → timers/cancel_spec.rb} +12 -13
- data/spec/{events_spec.rb → timers/events_spec.rb} +20 -21
- data/spec/{every_spec.rb → timers/every_spec.rb} +1 -2
- data/spec/{group_spec.rb → timers/group_spec.rb} +19 -18
- data/spec/{performance_spec.rb → timers/performance_spec.rb} +38 -42
- data/spec/timers/strict_spec.rb +36 -0
- data/spec/{timeout_spec.rb → timers/wait_spec.rb} +11 -10
- data/timers.gemspec +16 -13
- metadata +29 -41
- data/spec/strict_spec.rb +0 -37
data/lib/timers/timer.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module Timers
|
3
|
-
# An individual timer set to fire a given proc at a given time. A timer is
|
4
|
+
# An individual timer set to fire a given proc at a given time. A timer is
|
4
5
|
# always connected to a Timer::Group but it would ONLY be in @group.timers
|
5
6
|
# if it also has a @handle specified. Otherwise it is either PAUSED or has
|
6
7
|
# been FIRED and is not recurring. You can manually enter this state by
|
@@ -11,14 +12,14 @@ module Timers
|
|
11
12
|
|
12
13
|
def initialize(group, interval, recurring = false, offset = nil, &block)
|
13
14
|
@group = group
|
14
|
-
|
15
|
+
|
15
16
|
@interval = interval
|
16
17
|
@recurring = recurring
|
17
18
|
@block = block
|
18
19
|
@offset = offset
|
19
|
-
|
20
|
+
|
20
21
|
@handle = nil
|
21
|
-
|
22
|
+
|
22
23
|
# If a start offset was supplied, use that, otherwise use the current timers offset.
|
23
24
|
reset(@offset || @group.current_offset)
|
24
25
|
end
|
@@ -29,41 +30,41 @@ module Timers
|
|
29
30
|
|
30
31
|
def pause
|
31
32
|
return if paused?
|
32
|
-
|
33
|
+
|
33
34
|
@group.timers.delete self
|
34
35
|
@group.paused_timers.add self
|
35
|
-
|
36
|
+
|
36
37
|
@handle.cancel! if @handle
|
37
38
|
@handle = nil
|
38
39
|
end
|
39
40
|
|
40
41
|
def resume
|
41
42
|
return unless paused?
|
42
|
-
|
43
|
+
|
43
44
|
@group.paused_timers.delete self
|
44
|
-
|
45
|
+
|
45
46
|
# This will add us back to the group:
|
46
47
|
reset
|
47
48
|
end
|
48
49
|
|
49
|
-
|
50
|
+
alias continue resume
|
50
51
|
|
51
52
|
# Extend this timer
|
52
53
|
def delay(seconds)
|
53
54
|
@handle.cancel! if @handle
|
54
|
-
|
55
|
+
|
55
56
|
@offset += seconds
|
56
|
-
|
57
|
+
|
57
58
|
@handle = @group.events.schedule(@offset, self)
|
58
59
|
end
|
59
|
-
|
60
|
+
|
60
61
|
# Cancel this timer. Do not call while paused.
|
61
62
|
def cancel
|
62
63
|
return unless @handle
|
63
|
-
|
64
|
+
|
64
65
|
@handle.cancel! if @handle
|
65
66
|
@handle = nil
|
66
|
-
|
67
|
+
|
67
68
|
# This timer is no longer valid:
|
68
69
|
@group.timers.delete self if @group
|
69
70
|
end
|
@@ -77,9 +78,9 @@ module Timers
|
|
77
78
|
else
|
78
79
|
@group.timers << self
|
79
80
|
end
|
80
|
-
|
81
|
+
|
81
82
|
@offset = Float(offset) + @interval
|
82
|
-
|
83
|
+
|
83
84
|
@handle = @group.events.schedule(@offset, self)
|
84
85
|
end
|
85
86
|
|
@@ -95,11 +96,11 @@ module Timers
|
|
95
96
|
end
|
96
97
|
|
97
98
|
@block.call(offset)
|
98
|
-
|
99
|
+
|
99
100
|
cancel unless recurring
|
100
101
|
end
|
101
102
|
|
102
|
-
|
103
|
+
alias call fire
|
103
104
|
|
104
105
|
# Number of seconds until next fire / since last fire
|
105
106
|
def fires_in
|
@@ -108,14 +109,14 @@ module Timers
|
|
108
109
|
|
109
110
|
# Inspect a timer
|
110
111
|
def inspect
|
111
|
-
str = "#<Timers::Timer:#{object_id.to_s(16)} "
|
112
|
+
str = "#<Timers::Timer:#{object_id.to_s(16)} ".dup
|
112
113
|
|
113
114
|
if @offset
|
114
|
-
if fires_in >= 0
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
115
|
+
str << if fires_in >= 0
|
116
|
+
"fires in #{fires_in} seconds"
|
117
|
+
else
|
118
|
+
"fired #{fires_in.abs} seconds ago"
|
119
|
+
end
|
119
120
|
|
120
121
|
str << ", recurs every #{interval}" if recurring
|
121
122
|
else
|
data/lib/timers/version.rb
CHANGED
data/lib/timers/wait.rb
CHANGED
@@ -1,48 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
|
-
require
|
3
|
+
require "hitimes"
|
3
4
|
|
4
5
|
module Timers
|
5
6
|
# An exclusive, monotonic timeout class.
|
6
7
|
class Wait
|
7
8
|
def self.for(duration, &block)
|
8
9
|
if duration
|
9
|
-
timeout =
|
10
|
-
|
10
|
+
timeout = new(duration)
|
11
|
+
|
11
12
|
timeout.while_time_remaining(&block)
|
12
13
|
else
|
13
|
-
|
14
|
+
loop do
|
14
15
|
yield(nil)
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
18
|
-
|
19
|
+
|
19
20
|
def initialize(duration)
|
20
21
|
@duration = duration
|
21
22
|
@remaining = true
|
22
23
|
end
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
|
25
|
+
attr_reader :duration
|
26
|
+
attr_reader :remaining
|
27
|
+
|
27
28
|
# Yields while time remains for work to be done:
|
28
|
-
def while_time_remaining
|
29
|
+
def while_time_remaining
|
29
30
|
@interval = Hitimes::Interval.new
|
30
31
|
@interval.start
|
31
|
-
|
32
|
-
while time_remaining?
|
33
|
-
yield @remaining
|
34
|
-
end
|
32
|
+
|
33
|
+
yield @remaining while time_remaining?
|
35
34
|
ensure
|
36
35
|
@interval.stop
|
37
36
|
@interval = nil
|
38
37
|
end
|
39
|
-
|
38
|
+
|
40
39
|
private
|
41
|
-
|
40
|
+
|
42
41
|
def time_remaining?
|
43
42
|
@remaining = (@duration - @interval.duration)
|
44
|
-
|
45
|
-
|
43
|
+
|
44
|
+
@remaining > 0
|
46
45
|
end
|
47
46
|
end
|
48
47
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "coveralls"
|
2
4
|
Coveralls.wear!
|
3
5
|
|
4
|
-
require
|
5
|
-
require
|
6
|
+
require "bundler/setup"
|
7
|
+
require "timers"
|
6
8
|
|
7
9
|
# Level of accuracy enforced by tests (50ms)
|
8
10
|
TIMER_QUANTUM = 0.05
|
@@ -1,12 +1,11 @@
|
|
1
|
-
|
2
|
-
require 'spec_helper'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
RSpec.describe Timers::Group do
|
5
4
|
it "should be able to cancel twice" do
|
6
5
|
fired = false
|
7
6
|
|
8
7
|
timer = subject.after(0.1) { fired = true }
|
9
|
-
|
8
|
+
|
10
9
|
2.times do
|
11
10
|
timer.cancel
|
12
11
|
subject.wait
|
@@ -14,32 +13,32 @@ RSpec.describe Timers::Group do
|
|
14
13
|
|
15
14
|
expect(fired).to be false
|
16
15
|
end
|
17
|
-
|
16
|
+
|
18
17
|
it "should be possble to reset after cancel" do
|
19
18
|
fired = false
|
20
|
-
|
19
|
+
|
21
20
|
timer = subject.after(0.1) { fired = true }
|
22
21
|
timer.cancel
|
23
|
-
|
22
|
+
|
24
23
|
subject.wait
|
25
|
-
|
24
|
+
|
26
25
|
timer.reset
|
27
|
-
|
26
|
+
|
28
27
|
subject.wait
|
29
|
-
|
28
|
+
|
30
29
|
expect(fired).to be true
|
31
30
|
end
|
32
|
-
|
31
|
+
|
33
32
|
it "should cancel and remove one shot timers after they fire" do
|
34
33
|
x = 0
|
35
34
|
|
36
|
-
Timers::Wait.for(2) do |
|
35
|
+
Timers::Wait.for(2) do |_remaining|
|
37
36
|
timer = subject.every(0.2) { x += 1 }
|
38
37
|
subject.after(0.1) { timer.cancel }
|
39
|
-
|
38
|
+
|
40
39
|
subject.wait
|
41
40
|
end
|
42
|
-
|
41
|
+
|
43
42
|
expect(subject.timers).to be_empty
|
44
43
|
expect(x).to be == 0
|
45
44
|
end
|
@@ -1,57 +1,56 @@
|
|
1
|
-
|
2
|
-
require 'spec_helper'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
RSpec.describe Timers::Events do
|
5
4
|
it "should register an event" do
|
6
5
|
fired = false
|
7
|
-
|
8
|
-
callback = proc do |
|
6
|
+
|
7
|
+
callback = proc do |_time|
|
9
8
|
fired = true
|
10
9
|
end
|
11
|
-
|
10
|
+
|
12
11
|
subject.schedule(0.1, callback)
|
13
|
-
|
12
|
+
|
14
13
|
expect(subject.size).to be == 1
|
15
|
-
|
14
|
+
|
16
15
|
subject.fire(0.15)
|
17
|
-
|
16
|
+
|
18
17
|
expect(subject.size).to be == 0
|
19
|
-
|
18
|
+
|
20
19
|
expect(fired).to be true
|
21
20
|
end
|
22
|
-
|
21
|
+
|
23
22
|
it "should register events in order" do
|
24
23
|
fired = []
|
25
|
-
|
24
|
+
|
26
25
|
times = [0.95, 0.1, 0.3, 0.5, 0.4, 0.2, 0.01, 0.9]
|
27
|
-
|
26
|
+
|
28
27
|
times.each do |requested_time|
|
29
|
-
callback = proc do |
|
28
|
+
callback = proc do |_time|
|
30
29
|
fired << requested_time
|
31
30
|
end
|
32
|
-
|
31
|
+
|
33
32
|
subject.schedule(requested_time, callback)
|
34
33
|
end
|
35
|
-
|
34
|
+
|
36
35
|
subject.fire(0.5)
|
37
36
|
expect(fired).to be == times.sort.first(6)
|
38
|
-
|
37
|
+
|
39
38
|
subject.fire(1.0)
|
40
39
|
expect(fired).to be == times.sort
|
41
40
|
end
|
42
|
-
|
41
|
+
|
43
42
|
it "should fire events with the time they were fired at" do
|
44
43
|
fired_at = :not_fired
|
45
|
-
|
44
|
+
|
46
45
|
callback = proc do |time|
|
47
46
|
# The time we actually were fired at:
|
48
47
|
fired_at = time
|
49
48
|
end
|
50
|
-
|
49
|
+
|
51
50
|
subject.schedule(0.5, callback)
|
52
|
-
|
51
|
+
|
53
52
|
subject.fire(1.0)
|
54
|
-
|
53
|
+
|
55
54
|
expect(fired_at).to be == 1.0
|
56
55
|
end
|
57
56
|
end
|
@@ -1,19 +1,18 @@
|
|
1
|
-
|
2
|
-
require 'spec_helper'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
RSpec.describe Timers::Group do
|
5
4
|
describe "#wait" do
|
6
5
|
it "calls the wait block with nil" do
|
7
6
|
called = false
|
8
|
-
|
7
|
+
|
9
8
|
subject.wait do |interval|
|
10
|
-
expect(interval).to
|
9
|
+
expect(interval).to be_nil
|
11
10
|
called = true
|
12
11
|
end
|
13
|
-
|
12
|
+
|
14
13
|
expect(called).to be true
|
15
14
|
end
|
16
|
-
|
15
|
+
|
17
16
|
it "calls the wait block with an interval" do
|
18
17
|
called = false
|
19
18
|
fired = false
|
@@ -30,7 +29,7 @@ RSpec.describe Timers::Group do
|
|
30
29
|
expect(fired).to be true
|
31
30
|
end
|
32
31
|
end
|
33
|
-
|
32
|
+
|
34
33
|
it "sleeps until the next timer" do
|
35
34
|
interval = TIMER_QUANTUM * 2
|
36
35
|
started_at = Time.now
|
@@ -107,7 +106,7 @@ RSpec.describe Timers::Group do
|
|
107
106
|
|
108
107
|
describe "pause and continue timers" do
|
109
108
|
before(:each) do
|
110
|
-
@interval
|
109
|
+
@interval = TIMER_QUANTUM * 2
|
111
110
|
|
112
111
|
@fired = false
|
113
112
|
@timer = subject.after(@interval) { @fired = true }
|
@@ -125,10 +124,10 @@ RSpec.describe Timers::Group do
|
|
125
124
|
@timer.pause
|
126
125
|
subject.wait
|
127
126
|
@timer.resume
|
128
|
-
|
127
|
+
|
129
128
|
sleep @timer.interval
|
130
129
|
subject.wait
|
131
|
-
|
130
|
+
|
132
131
|
expect(@fired).to be true
|
133
132
|
end
|
134
133
|
|
@@ -143,18 +142,20 @@ RSpec.describe Timers::Group do
|
|
143
142
|
subject.pause
|
144
143
|
subject.wait
|
145
144
|
subject.resume
|
146
|
-
|
147
|
-
# We need to wait until we are sure both timers will fire, otherwise highly accurate clocks
|
145
|
+
|
146
|
+
# We need to wait until we are sure both timers will fire, otherwise highly accurate clocks
|
147
|
+
# (e.g. JVM)may only fire the first timer, but not the second, because they are actually
|
148
|
+
# schedueled at different times.
|
148
149
|
sleep TIMER_QUANTUM * 2
|
149
150
|
subject.wait
|
150
|
-
|
151
|
+
|
151
152
|
expect(@fired).to be true
|
152
153
|
expect(@fired2).to be true
|
153
154
|
end
|
154
155
|
|
155
156
|
it "can fire the timer directly" do
|
156
157
|
fired = false
|
157
|
-
timer = subject.after(
|
158
|
+
timer = subject.after(TIMER_QUANTUM * 1) { fired = true }
|
158
159
|
timer.pause
|
159
160
|
subject.wait
|
160
161
|
expect(fired).not_to be true
|
@@ -163,7 +164,6 @@ RSpec.describe Timers::Group do
|
|
163
164
|
timer.fire
|
164
165
|
expect(fired).to be true
|
165
166
|
end
|
166
|
-
|
167
167
|
end
|
168
168
|
|
169
169
|
describe "delay timer" do
|
@@ -200,7 +200,7 @@ RSpec.describe Timers::Group do
|
|
200
200
|
end
|
201
201
|
end
|
202
202
|
|
203
|
-
describe "
|
203
|
+
describe "#inspect" do
|
204
204
|
it "before firing" do
|
205
205
|
fired = false
|
206
206
|
timer = subject.after(TIMER_QUANTUM * 5) { fired = true }
|
@@ -225,11 +225,12 @@ RSpec.describe Timers::Group do
|
|
225
225
|
|
226
226
|
subject.wait
|
227
227
|
expect(result).not_to be_empty
|
228
|
-
|
228
|
+
regex = /\A#<Timers::Timer:[\da-f]+ fires in [-\.\de]+ seconds, recurs every #{format("%0.2f", TIMER_QUANTUM)}>\Z/
|
229
|
+
expect(timer.inspect).to match(regex)
|
229
230
|
end
|
230
231
|
end
|
231
232
|
|
232
|
-
describe "fires_in" do
|
233
|
+
describe "#fires_in" do
|
233
234
|
let(:interval) { TIMER_QUANTUM * 2 }
|
234
235
|
|
235
236
|
it "calculates the interval until the next fire if it's recurring" do
|