timers 4.2.0 → 4.3.3

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/.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