timers 4.2.0 → 4.3.3

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --warnings
3
- --require spec_helper
data/.travis.yml DELETED
@@ -1,19 +0,0 @@
1
- language: ruby
2
- sudo: false
3
- dist: xenial
4
- cache: bundler
5
-
6
- matrix:
7
- include:
8
- - rvm: 2.3
9
- - rvm: 2.4
10
- - rvm: 2.5
11
- - rvm: 2.6
12
- - rvm: jruby-head
13
- - rvm: truffleruby
14
- - rvm: ruby-head
15
- - rvm: rbx-3
16
- allow_failures:
17
- - rvm: ruby-head
18
- - rvm: rbx-3
19
- - rvm: truffleruby
data/Gemfile DELETED
@@ -1,15 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
4
-
5
- group :development do
6
- gem 'pry'
7
- end
8
-
9
- group :test do
10
- gem 'benchmark-ips'
11
- gem "ruby-prof", platform: :mri
12
-
13
- gem 'simplecov'
14
- gem 'coveralls'
15
- end
data/README.md DELETED
@@ -1,149 +0,0 @@
1
- # Timers
2
-
3
- Collections of one-shot and periodic timers, intended for use with event loops such as [async].
4
-
5
- [![Build Status](https://secure.travis-ci.org/socketry/timers.svg)](https://travis-ci.org/socketry/timers)
6
- [![Code Climate](https://codeclimate.com/github/socketry/timers.svg)](https://codeclimate.com/github/socketry/timers)
7
- [![Coverage Status](https://coveralls.io/repos/socketry/timers/badge.svg)](https://coveralls.io/r/socketry/timers)
8
-
9
- [async]: https://github.com/socketry/async
10
-
11
- ## Installation
12
-
13
- Add this line to your application's Gemfile:
14
-
15
- ```ruby
16
- gem 'timers'
17
- ```
18
-
19
- And then execute:
20
-
21
- $ bundle
22
-
23
- Or install it yourself as:
24
-
25
- $ gem install timers
26
-
27
- ## Usage
28
-
29
- Create a new timer group with `Timers::Group.new`:
30
-
31
- ```ruby
32
- require 'timers'
33
-
34
- timers = Timers::Group.new
35
- ```
36
-
37
- Schedule a proc to run after 5 seconds with `Timers::Group#after`:
38
-
39
- ```ruby
40
- five_second_timer = timers.after(5) { puts "Take five" }
41
- ```
42
-
43
- The `five_second_timer` variable is now bound to a Timers::Timer object. To
44
- cancel a timer, use `Timers::Timer#cancel`
45
-
46
- Once you've scheduled a timer, you can wait until the next timer fires with `Timers::Group#wait`:
47
-
48
- ```ruby
49
- # Waits 5 seconds
50
- timers.wait
51
-
52
- # The script will now print "Take five"
53
- ```
54
-
55
- You can schedule a block to run periodically with `Timers::Group#every`:
56
-
57
- ```ruby
58
- every_five_seconds = timers.every(5) { puts "Another 5 seconds" }
59
-
60
- loop { timers.wait }
61
- ```
62
-
63
- You can also schedule a block to run immediately and periodically with `Timers::Group#now_and_every`:
64
- ```ruby
65
- now_and_every_five_seconds = timers.now_and_every(5) { puts "Now and in another 5 seconds" }
66
-
67
- loop { timers.wait }
68
- ```
69
-
70
- If you'd like another method to do the waiting for you, e.g. `Kernel.select`,
71
- you can use `Timers::Group#wait_interval` to obtain the amount of time to wait. When
72
- a timeout is encountered, you can fire all pending timers with `Timers::Group#fire`:
73
-
74
- ```ruby
75
- loop do
76
- interval = timers.wait_interval
77
- ready_readers, ready_writers = select readers, writers, nil, interval
78
-
79
- if ready_readers || ready_writers
80
- # Handle IO
81
- ...
82
- else
83
- # Timeout!
84
- timers.fire
85
- end
86
- end
87
- ```
88
-
89
- You can also pause and continue individual timers, or all timers:
90
-
91
- ```ruby
92
- paused_timer = timers.every(5) { puts "I was paused" }
93
-
94
- paused_timer.pause
95
- 10.times { timers.wait } # will not fire paused timer
96
-
97
- paused_timer.resume
98
- 10.times { timers.wait } # will fire timer
99
-
100
- timers.pause
101
- 10.times { timers.wait } # will not fire any timers
102
-
103
- timers.resume
104
- 10.times { timers.wait } # will fire all timers
105
- ```
106
-
107
- ## Contributing
108
-
109
- 1. Fork it
110
- 2. Create your feature branch (`git checkout -b my-new-feature`)
111
- 3. Commit your changes (`git commit -am 'Add some feature'`)
112
- 4. Push to the branch (`git push origin my-new-feature`)
113
- 5. Create new Pull Request
114
-
115
- ## License
116
-
117
- Released under the MIT license.
118
-
119
- Copyright, 2018, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
120
- Copyright, 2016, by [Tony Arcieri](bascule@gmail.com).
121
- Copyright, 2016, by Jeremy Hinegardner.
122
- Copyright, 2016, by Sean Gregory.
123
- Copyright, 2016, by Chuck Remes.
124
- Copyright, 2016, by Utenmiki.
125
- Copyright, 2016, by Ron Evans.
126
- Copyright, 2016, by Larry Lv.
127
- Copyright, 2016, by Bruno Enten.
128
- Copyright, 2016, by Jesse Cooke.
129
- Copyright, 2016, by Nicholas Evans.
130
- Copyright, 2016, by Dimitrij Denissenko.
131
- Copyright, 2016, by Ryan LeCompte.
132
-
133
- Permission is hereby granted, free of charge, to any person obtaining a copy
134
- of this software and associated documentation files (the "Software"), to deal
135
- in the Software without restriction, including without limitation the rights
136
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
137
- copies of the Software, and to permit persons to whom the Software is
138
- furnished to do so, subject to the following conditions:
139
-
140
- The above copyright notice and this permission notice shall be included in
141
- all copies or substantial portions of the Software.
142
-
143
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
144
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
145
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
146
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
147
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
148
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
149
- THE SOFTWARE.
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:test)
5
-
6
- task :default => :test
data/spec/spec_helper.rb DELETED
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- # This file is part of the "timers" project and released under the MIT license.
4
- #
5
- # Copyright, 2018, by Samuel Williams. All rights reserved.
6
- #
7
-
8
- # Level of accuracy enforced by tests (50ms)
9
- TIMER_QUANTUM = 0.05
10
-
11
- if ENV['COVERAGE'] || ENV['TRAVIS']
12
- begin
13
- require 'simplecov'
14
-
15
- SimpleCov.start do
16
- add_filter "/spec/"
17
- end
18
-
19
- if ENV['TRAVIS']
20
- require 'coveralls'
21
- Coveralls.wear!
22
- end
23
- rescue LoadError
24
- warn "Could not load simplecov: #{$!}"
25
- end
26
- end
27
-
28
- require "bundler/setup"
29
- require "timers"
30
-
31
- RSpec.configure do |config|
32
- # Enable flags like --only-failures and --next-failure
33
- config.example_status_persistence_file_path = ".rspec_status"
34
-
35
- config.expect_with :rspec do |c|
36
- c.syntax = :expect
37
- end
38
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- # This file is part of the "timers" project and released under the MIT license.
4
- #
5
- # Copyright, 2018, by Samuel Williams. All rights reserved.
6
- #
7
-
8
- RSpec.describe Timers::Group do
9
- it "should be able to cancel twice" do
10
- fired = false
11
-
12
- timer = subject.after(0.1) { fired = true }
13
-
14
- 2.times do
15
- timer.cancel
16
- subject.wait
17
- end
18
-
19
- expect(fired).to be false
20
- end
21
-
22
- it "should be possble to reset after cancel" do
23
- fired = false
24
-
25
- timer = subject.after(0.1) { fired = true }
26
- timer.cancel
27
-
28
- subject.wait
29
-
30
- timer.reset
31
-
32
- subject.wait
33
-
34
- expect(fired).to be true
35
- end
36
-
37
- it "should cancel and remove one shot timers after they fire" do
38
- x = 0
39
-
40
- Timers::Wait.for(2) do |_remaining|
41
- timer = subject.every(0.2) { x += 1 }
42
- subject.after(0.1) { timer.cancel }
43
-
44
- subject.wait
45
- end
46
-
47
- expect(subject.timers).to be_empty
48
- expect(x).to be == 0
49
- end
50
- end
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- # This file is part of the "timers" project and released under the MIT license.
4
- #
5
- # Copyright, 2018, by Samuel Williams. All rights reserved.
6
- #
7
-
8
- RSpec.describe Timers::Events do
9
- it "should register an event" do
10
- fired = false
11
-
12
- callback = proc do |_time|
13
- fired = true
14
- end
15
-
16
- subject.schedule(0.1, callback)
17
-
18
- expect(subject.size).to be == 1
19
-
20
- subject.fire(0.15)
21
-
22
- expect(subject.size).to be == 0
23
-
24
- expect(fired).to be true
25
- end
26
-
27
- it "should register events in order" do
28
- fired = []
29
-
30
- times = [0.95, 0.1, 0.3, 0.5, 0.4, 0.2, 0.01, 0.9]
31
-
32
- times.each do |requested_time|
33
- callback = proc do |_time|
34
- fired << requested_time
35
- end
36
-
37
- subject.schedule(requested_time, callback)
38
- end
39
-
40
- subject.fire(0.5)
41
- expect(fired).to be == times.sort.first(6)
42
-
43
- subject.fire(1.0)
44
- expect(fired).to be == times.sort
45
- end
46
-
47
- it "should fire events with the time they were fired at" do
48
- fired_at = :not_fired
49
-
50
- callback = proc do |time|
51
- # The time we actually were fired at:
52
- fired_at = time
53
- end
54
-
55
- subject.schedule(0.5, callback)
56
-
57
- subject.fire(1.0)
58
-
59
- expect(fired_at).to be == 1.0
60
- end
61
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- # This file is part of the "timers" project and released under the MIT license.
4
- #
5
- # Copyright, 2018, by Samuel Williams. All rights reserved.
6
- #
7
-
8
- RSpec.describe Timers::Group do
9
- it "should fire several times" do
10
- result = []
11
-
12
- subject.every(0.7) { result << :a }
13
- subject.every(2.3) { result << :b }
14
- subject.every(1.3) { result << :c }
15
- subject.every(2.4) { result << :d }
16
-
17
- Timers::Wait.for(2.5) do |remaining|
18
- subject.wait if subject.wait_interval < remaining
19
- end
20
-
21
- expect(result).to be == [:a, :c, :a, :a, :b, :d]
22
- end
23
-
24
- it "should fire immediately and then several times later" do
25
- result = []
26
-
27
- subject.every(0.7) { result << :a }
28
- subject.every(2.3) { result << :b }
29
- subject.now_and_every(1.3) { result << :c }
30
- subject.now_and_every(2.4) { result << :d }
31
-
32
- Timers::Wait.for(2.5) do |remaining|
33
- subject.wait if subject.wait_interval < remaining
34
- end
35
-
36
- expect(result).to be == [:c, :d, :a, :c, :a, :a, :b, :d]
37
- end
38
- end
@@ -1,260 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- # This file is part of the "timers" project and released under the MIT license.
4
- #
5
- # Copyright, 2018, by Samuel Williams. All rights reserved.
6
- #
7
-
8
- RSpec.describe Timers::Group do
9
- describe "#wait" do
10
- it "calls the wait block with nil" do
11
- called = false
12
-
13
- subject.wait do |interval|
14
- expect(interval).to be_nil
15
- called = true
16
- end
17
-
18
- expect(called).to be true
19
- end
20
-
21
- it "calls the wait block with an interval" do
22
- called = false
23
- fired = false
24
-
25
- subject.after(0.1) { fired = true }
26
-
27
- subject.wait do |interval|
28
- expect(interval).to be_within(TIMER_QUANTUM).of(0.1)
29
- called = true
30
- sleep 0.2
31
- end
32
-
33
- expect(called).to be true
34
- expect(fired).to be true
35
- end
36
- end
37
-
38
- it "sleeps until the next timer" do
39
- interval = TIMER_QUANTUM * 2
40
- started_at = Time.now
41
-
42
- fired = false
43
- subject.after(interval) { fired = true }
44
- subject.wait
45
-
46
- expect(fired).to be true
47
- expect(Time.now - started_at).to be_within(TIMER_QUANTUM).of interval
48
- end
49
-
50
- it "fires instantly when next timer is in the past" do
51
- fired = false
52
- subject.after(TIMER_QUANTUM) { fired = true }
53
- sleep(TIMER_QUANTUM * 2)
54
- subject.wait
55
-
56
- expect(fired).to be true
57
- end
58
-
59
- it "calculates the interval until the next timer should fire" do
60
- interval = 0.1
61
-
62
- subject.after(interval)
63
- expect(subject.wait_interval).to be_within(TIMER_QUANTUM).of interval
64
-
65
- sleep(interval)
66
- expect(subject.wait_interval).to be <= 0
67
- end
68
-
69
- it "fires timers in the correct order" do
70
- result = []
71
-
72
- subject.after(TIMER_QUANTUM * 2) { result << :two }
73
- subject.after(TIMER_QUANTUM * 3) { result << :three }
74
- subject.after(TIMER_QUANTUM * 1) { result << :one }
75
-
76
- sleep TIMER_QUANTUM * 4
77
- subject.fire
78
-
79
- expect(result).to eq [:one, :two, :three]
80
- end
81
-
82
- it "raises TypeError if given an invalid time" do
83
- expect do
84
- subject.after(nil) { nil }
85
- end.to raise_exception(TypeError)
86
- end
87
-
88
- describe "recurring timers" do
89
- it "continues to fire the timers at each interval" do
90
- result = []
91
-
92
- subject.every(TIMER_QUANTUM * 2) { result << :foo }
93
-
94
- sleep TIMER_QUANTUM * 3
95
- subject.fire
96
- expect(result).to eq [:foo]
97
-
98
- sleep TIMER_QUANTUM * 5
99
- subject.fire
100
- expect(result).to eq [:foo, :foo]
101
- end
102
- end
103
-
104
- it "calculates the proper interval to wait until firing" do
105
- interval_ms = 25
106
-
107
- subject.after(interval_ms / 1000.0)
108
-
109
- expect(subject.wait_interval).to be_within(TIMER_QUANTUM).of(interval_ms / 1000.0)
110
- end
111
-
112
- describe "pause and continue timers" do
113
- before(:each) do
114
- @interval = TIMER_QUANTUM * 2
115
-
116
- @fired = false
117
- @timer = subject.after(@interval) { @fired = true }
118
- @fired2 = false
119
- @timer2 = subject.after(@interval) { @fired2 = true }
120
- end
121
-
122
- it "does not fire when paused" do
123
- @timer.pause
124
- subject.wait
125
- expect(@fired).to be false
126
- end
127
-
128
- it "fires when continued after pause" do
129
- @timer.pause
130
- subject.wait
131
- @timer.resume
132
-
133
- sleep @timer.interval
134
- subject.wait
135
-
136
- expect(@fired).to be true
137
- end
138
-
139
- it "can pause all timers at once" do
140
- subject.pause
141
- subject.wait
142
- expect(@fired).to be false
143
- expect(@fired2).to be false
144
- end
145
-
146
- it "can continue all timers at once" do
147
- subject.pause
148
- subject.wait
149
- subject.resume
150
-
151
- # We need to wait until we are sure both timers will fire, otherwise highly accurate clocks
152
- # (e.g. JVM)may only fire the first timer, but not the second, because they are actually
153
- # schedueled at different times.
154
- sleep TIMER_QUANTUM * 2
155
- subject.wait
156
-
157
- expect(@fired).to be true
158
- expect(@fired2).to be true
159
- end
160
-
161
- it "can fire the timer directly" do
162
- fired = false
163
- timer = subject.after(TIMER_QUANTUM * 1) { fired = true }
164
- timer.pause
165
- subject.wait
166
- expect(fired).not_to be true
167
- timer.resume
168
- expect(fired).not_to be true
169
- timer.fire
170
- expect(fired).to be true
171
- end
172
- end
173
-
174
- describe "delay timer" do
175
- it "adds appropriate amount of time to timer" do
176
- timer = subject.after(10)
177
- timer.delay(5)
178
- expect(timer.offset - subject.current_offset).to be_within(TIMER_QUANTUM).of(15)
179
- end
180
- end
181
-
182
- describe "delay timer collection" do
183
- it "delay on set adds appropriate amount of time to all timers" do
184
- timer = subject.after(10)
185
- timer2 = subject.after(20)
186
- subject.delay(5)
187
- expect(timer.offset - subject.current_offset).to be_within(TIMER_QUANTUM).of(15)
188
- expect(timer2.offset - subject.current_offset).to be_within(TIMER_QUANTUM).of(25)
189
- end
190
- end
191
-
192
- describe "on delaying a timer" do
193
- it "fires timers in the correct order" do
194
- result = []
195
-
196
- subject.after(TIMER_QUANTUM * 2) { result << :two }
197
- subject.after(TIMER_QUANTUM * 3) { result << :three }
198
- first = subject.after(TIMER_QUANTUM * 1) { result << :one }
199
- first.delay(TIMER_QUANTUM * 3)
200
-
201
- sleep TIMER_QUANTUM * 5
202
- subject.fire
203
-
204
- expect(result).to eq [:two, :three, :one]
205
- end
206
- end
207
-
208
- describe "#inspect" do
209
- it "before firing" do
210
- fired = false
211
- timer = subject.after(TIMER_QUANTUM * 5) { fired = true }
212
- timer.pause
213
- expect(fired).not_to be true
214
- expect(timer.inspect).to match(/\A#<Timers::Timer:0x[\da-f]+ fires in [-\.\de]+ seconds>\Z/)
215
- end
216
-
217
- it "after firing" do
218
- fired = false
219
- timer = subject.after(TIMER_QUANTUM) { fired = true }
220
-
221
- subject.wait
222
-
223
- expect(fired).to be true
224
- expect(timer.inspect).to match(/\A#<Timers::Timer:0x[\da-f]+ fired [-\.\de]+ seconds ago>\Z/)
225
- end
226
-
227
- it "recurring firing" do
228
- result = []
229
- timer = subject.every(TIMER_QUANTUM) { result << :foo }
230
-
231
- subject.wait
232
- expect(result).not_to be_empty
233
- regex = /\A#<Timers::Timer:0x[\da-f]+ fires in [-\.\de]+ seconds, recurs every #{format("%0.2f", TIMER_QUANTUM)}>\Z/
234
- expect(timer.inspect).to match(regex)
235
- end
236
- end
237
-
238
- describe "#fires_in" do
239
- let(:interval) { TIMER_QUANTUM * 2 }
240
-
241
- it "calculates the interval until the next fire if it's recurring" do
242
- timer = subject.every(interval) { true }
243
- expect(timer.fires_in).to be_within(TIMER_QUANTUM).of(interval)
244
- end
245
-
246
- context "when timer is not recurring" do
247
- let!(:timer) { subject.after(interval) { true } }
248
-
249
- it "calculates the interval until the next fire if it hasn't already fired" do
250
- expect(timer.fires_in).to be_within(TIMER_QUANTUM).of(interval)
251
- end
252
-
253
- it "calculates the interval since last fire if already fired" do
254
- subject.wait
255
- sleep(interval)
256
- expect(timer.fires_in).to be_within(TIMER_QUANTUM).of(0 - interval)
257
- end
258
- end
259
- end
260
- end