timers 4.1.2 → 4.3.2

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/Rakefile DELETED
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
- require "bundler/gem_tasks"
3
-
4
- require "rspec/core/rake_task"
5
- RSpec::Core::RakeTask.new
6
-
7
- require "rubocop/rake_task"
8
- RuboCop::RakeTask.new
9
-
10
- task default: %w(spec rubocop)
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "coveralls"
4
- Coveralls.wear!
5
-
6
- require "bundler/setup"
7
- require "timers"
8
-
9
- # Level of accuracy enforced by tests (50ms)
10
- TIMER_QUANTUM = 0.05
11
-
12
- RSpec.configure do |config|
13
- # Setting this config option `false` removes rspec-core's monkey patching of the
14
- # top level methods like `describe`, `shared_examples_for` and `shared_context`
15
- # on `main` and `Module`. The methods are always available through the `RSpec`
16
- # module like `RSpec.describe` regardless of this setting.
17
- # For backwards compatibility this defaults to `true`.
18
- #
19
- # https://relishapp.com/rspec/rspec-core/v/3-0/docs/configuration/global-namespace-dsl
20
- config.expose_dsl_globally = false
21
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Timers::Group do
4
- it "should be able to cancel twice" do
5
- fired = false
6
-
7
- timer = subject.after(0.1) { fired = true }
8
-
9
- 2.times do
10
- timer.cancel
11
- subject.wait
12
- end
13
-
14
- expect(fired).to be false
15
- end
16
-
17
- it "should be possble to reset after cancel" do
18
- fired = false
19
-
20
- timer = subject.after(0.1) { fired = true }
21
- timer.cancel
22
-
23
- subject.wait
24
-
25
- timer.reset
26
-
27
- subject.wait
28
-
29
- expect(fired).to be true
30
- end
31
-
32
- it "should cancel and remove one shot timers after they fire" do
33
- x = 0
34
-
35
- Timers::Wait.for(2) do |_remaining|
36
- timer = subject.every(0.2) { x += 1 }
37
- subject.after(0.1) { timer.cancel }
38
-
39
- subject.wait
40
- end
41
-
42
- expect(subject.timers).to be_empty
43
- expect(x).to be == 0
44
- end
45
- end
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Timers::Events do
4
- it "should register an event" do
5
- fired = false
6
-
7
- callback = proc do |_time|
8
- fired = true
9
- end
10
-
11
- subject.schedule(0.1, callback)
12
-
13
- expect(subject.size).to be == 1
14
-
15
- subject.fire(0.15)
16
-
17
- expect(subject.size).to be == 0
18
-
19
- expect(fired).to be true
20
- end
21
-
22
- it "should register events in order" do
23
- fired = []
24
-
25
- times = [0.95, 0.1, 0.3, 0.5, 0.4, 0.2, 0.01, 0.9]
26
-
27
- times.each do |requested_time|
28
- callback = proc do |_time|
29
- fired << requested_time
30
- end
31
-
32
- subject.schedule(requested_time, callback)
33
- end
34
-
35
- subject.fire(0.5)
36
- expect(fired).to be == times.sort.first(6)
37
-
38
- subject.fire(1.0)
39
- expect(fired).to be == times.sort
40
- end
41
-
42
- it "should fire events with the time they were fired at" do
43
- fired_at = :not_fired
44
-
45
- callback = proc do |time|
46
- # The time we actually were fired at:
47
- fired_at = time
48
- end
49
-
50
- subject.schedule(0.5, callback)
51
-
52
- subject.fire(1.0)
53
-
54
- expect(fired_at).to be == 1.0
55
- end
56
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Timers::Group do
4
- it "should fire several times" do
5
- result = []
6
-
7
- subject.every(0.7) { result << :a }
8
- subject.every(2.3) { result << :b }
9
- subject.every(1.3) { result << :c }
10
- subject.every(2.4) { result << :d }
11
-
12
- Timers::Wait.for(2.5) do |remaining|
13
- subject.wait if subject.wait_interval < remaining
14
- end
15
-
16
- expect(result).to be == [:a, :c, :a, :a, :b, :d]
17
- end
18
-
19
- it "should fire immediately and then several times later" do
20
- result = []
21
-
22
- subject.every(0.7) { result << :a }
23
- subject.every(2.3) { result << :b }
24
- subject.now_and_every(1.3) { result << :c }
25
- subject.now_and_every(2.4) { result << :d }
26
-
27
- Timers::Wait.for(2.5) do |remaining|
28
- subject.wait if subject.wait_interval < remaining
29
- end
30
-
31
- expect(result).to be == [:c, :d, :a, :c, :a, :a, :b, :d]
32
- end
33
- end
@@ -1,255 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Timers::Group do
4
- describe "#wait" do
5
- it "calls the wait block with nil" do
6
- called = false
7
-
8
- subject.wait do |interval|
9
- expect(interval).to be_nil
10
- called = true
11
- end
12
-
13
- expect(called).to be true
14
- end
15
-
16
- it "calls the wait block with an interval" do
17
- called = false
18
- fired = false
19
-
20
- subject.after(0.1) { fired = true }
21
-
22
- subject.wait do |interval|
23
- expect(interval).to be_within(TIMER_QUANTUM).of(0.1)
24
- called = true
25
- sleep 0.2
26
- end
27
-
28
- expect(called).to be true
29
- expect(fired).to be true
30
- end
31
- end
32
-
33
- it "sleeps until the next timer" do
34
- interval = TIMER_QUANTUM * 2
35
- started_at = Time.now
36
-
37
- fired = false
38
- subject.after(interval) { fired = true }
39
- subject.wait
40
-
41
- expect(fired).to be true
42
- expect(Time.now - started_at).to be_within(TIMER_QUANTUM).of interval
43
- end
44
-
45
- it "fires instantly when next timer is in the past" do
46
- fired = false
47
- subject.after(TIMER_QUANTUM) { fired = true }
48
- sleep(TIMER_QUANTUM * 2)
49
- subject.wait
50
-
51
- expect(fired).to be true
52
- end
53
-
54
- it "calculates the interval until the next timer should fire" do
55
- interval = 0.1
56
-
57
- subject.after(interval)
58
- expect(subject.wait_interval).to be_within(TIMER_QUANTUM).of interval
59
-
60
- sleep(interval)
61
- expect(subject.wait_interval).to be <= 0
62
- end
63
-
64
- it "fires timers in the correct order" do
65
- result = []
66
-
67
- subject.after(TIMER_QUANTUM * 2) { result << :two }
68
- subject.after(TIMER_QUANTUM * 3) { result << :three }
69
- subject.after(TIMER_QUANTUM * 1) { result << :one }
70
-
71
- sleep TIMER_QUANTUM * 4
72
- subject.fire
73
-
74
- expect(result).to eq [:one, :two, :three]
75
- end
76
-
77
- it "raises TypeError if given an invalid time" do
78
- expect do
79
- subject.after(nil) { nil }
80
- end.to raise_exception(TypeError)
81
- end
82
-
83
- describe "recurring timers" do
84
- it "continues to fire the timers at each interval" do
85
- result = []
86
-
87
- subject.every(TIMER_QUANTUM * 2) { result << :foo }
88
-
89
- sleep TIMER_QUANTUM * 3
90
- subject.fire
91
- expect(result).to eq [:foo]
92
-
93
- sleep TIMER_QUANTUM * 5
94
- subject.fire
95
- expect(result).to eq [:foo, :foo]
96
- end
97
- end
98
-
99
- it "calculates the proper interval to wait until firing" do
100
- interval_ms = 25
101
-
102
- subject.after(interval_ms / 1000.0)
103
-
104
- expect(subject.wait_interval).to be_within(TIMER_QUANTUM).of(interval_ms / 1000.0)
105
- end
106
-
107
- describe "pause and continue timers" do
108
- before(:each) do
109
- @interval = TIMER_QUANTUM * 2
110
-
111
- @fired = false
112
- @timer = subject.after(@interval) { @fired = true }
113
- @fired2 = false
114
- @timer2 = subject.after(@interval) { @fired2 = true }
115
- end
116
-
117
- it "does not fire when paused" do
118
- @timer.pause
119
- subject.wait
120
- expect(@fired).to be false
121
- end
122
-
123
- it "fires when continued after pause" do
124
- @timer.pause
125
- subject.wait
126
- @timer.resume
127
-
128
- sleep @timer.interval
129
- subject.wait
130
-
131
- expect(@fired).to be true
132
- end
133
-
134
- it "can pause all timers at once" do
135
- subject.pause
136
- subject.wait
137
- expect(@fired).to be false
138
- expect(@fired2).to be false
139
- end
140
-
141
- it "can continue all timers at once" do
142
- subject.pause
143
- subject.wait
144
- subject.resume
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.
149
- sleep TIMER_QUANTUM * 2
150
- subject.wait
151
-
152
- expect(@fired).to be true
153
- expect(@fired2).to be true
154
- end
155
-
156
- it "can fire the timer directly" do
157
- fired = false
158
- timer = subject.after(TIMER_QUANTUM * 1) { fired = true }
159
- timer.pause
160
- subject.wait
161
- expect(fired).not_to be true
162
- timer.resume
163
- expect(fired).not_to be true
164
- timer.fire
165
- expect(fired).to be true
166
- end
167
- end
168
-
169
- describe "delay timer" do
170
- it "adds appropriate amount of time to timer" do
171
- timer = subject.after(10)
172
- timer.delay(5)
173
- expect(timer.offset - subject.current_offset).to be_within(TIMER_QUANTUM).of(15)
174
- end
175
- end
176
-
177
- describe "delay timer collection" do
178
- it "delay on set adds appropriate amount of time to all timers" do
179
- timer = subject.after(10)
180
- timer2 = subject.after(20)
181
- subject.delay(5)
182
- expect(timer.offset - subject.current_offset).to be_within(TIMER_QUANTUM).of(15)
183
- expect(timer2.offset - subject.current_offset).to be_within(TIMER_QUANTUM).of(25)
184
- end
185
- end
186
-
187
- describe "on delaying a timer" do
188
- it "fires timers in the correct order" do
189
- result = []
190
-
191
- subject.after(TIMER_QUANTUM * 2) { result << :two }
192
- subject.after(TIMER_QUANTUM * 3) { result << :three }
193
- first = subject.after(TIMER_QUANTUM * 1) { result << :one }
194
- first.delay(TIMER_QUANTUM * 3)
195
-
196
- sleep TIMER_QUANTUM * 5
197
- subject.fire
198
-
199
- expect(result).to eq [:two, :three, :one]
200
- end
201
- end
202
-
203
- describe "#inspect" do
204
- it "before firing" do
205
- fired = false
206
- timer = subject.after(TIMER_QUANTUM * 5) { fired = true }
207
- timer.pause
208
- expect(fired).not_to be true
209
- expect(timer.inspect).to match(/\A#<Timers::Timer:[\da-f]+ fires in [-\.\de]+ seconds>\Z/)
210
- end
211
-
212
- it "after firing" do
213
- fired = false
214
- timer = subject.after(TIMER_QUANTUM) { fired = true }
215
-
216
- subject.wait
217
-
218
- expect(fired).to be true
219
- expect(timer.inspect).to match(/\A#<Timers::Timer:[\da-f]+ fired [-\.\de]+ seconds ago>\Z/)
220
- end
221
-
222
- it "recurring firing" do
223
- result = []
224
- timer = subject.every(TIMER_QUANTUM) { result << :foo }
225
-
226
- subject.wait
227
- expect(result).not_to be_empty
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)
230
- end
231
- end
232
-
233
- describe "#fires_in" do
234
- let(:interval) { TIMER_QUANTUM * 2 }
235
-
236
- it "calculates the interval until the next fire if it's recurring" do
237
- timer = subject.every(interval) { true }
238
- expect(timer.fires_in).to be_within(TIMER_QUANTUM).of(interval)
239
- end
240
-
241
- context "when timer is not recurring" do
242
- let!(:timer) { subject.after(interval) { true } }
243
-
244
- it "calculates the interval until the next fire if it hasn't already fired" do
245
- expect(timer.fires_in).to be_within(TIMER_QUANTUM).of(interval)
246
- end
247
-
248
- it "calculates the interval since last fire if already fired" do
249
- subject.wait
250
- sleep(interval)
251
- expect(timer.fires_in).to be_within(TIMER_QUANTUM).of(0 - interval)
252
- end
253
- end
254
- end
255
- end
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Event based timers:
4
-
5
- # Serviced 31812 events in 2.39075272 seconds, 13306.320832794887 e/s.
6
- # Thread ID: 7336700
7
- # Fiber ID: 30106340
8
- # Total: 2.384043
9
- # Sort by: self_time
10
-
11
- # %self total self wait child calls name
12
- # 13.48 0.510 0.321 0.000 0.189 369133 Timers::Events::Handle#<=>
13
- # 8.12 0.194 0.194 0.000 0.000 427278 Timers::Events::Handle#to_f
14
- # 4.55 0.109 0.109 0.000 0.000 427278 Float#<=>
15
- # 4.40 1.857 0.105 0.000 1.752 466376 *Timers::Events#bsearch
16
- # 4.30 0.103 0.103 0.000 0.000 402945 Float#to_f
17
- # 2.65 0.063 0.063 0.000 0.000 33812 Array#insert
18
- # 2.64 1.850 0.063 0.000 1.787 33812 Timers::Events#schedule
19
- # 2.40 1.930 0.057 0.000 1.873 33812 Timers::Timer#reset
20
- # 1.89 1.894 0.045 0.000 1.849 31812 Timers::Timer#fire
21
- # 1.69 1.966 0.040 0.000 1.926 31812 Timers::Events::Handle#fire
22
- # 1.35 0.040 0.032 0.000 0.008 33812 Timers::Events::Handle#initialize
23
- # 1.29 0.044 0.031 0.000 0.013 44451 Timers::Group#current_offset
24
-
25
- # SortedSet based timers:
26
-
27
- # Serviced 32516 events in 66.753277275 seconds, 487.1072288781219 e/s.
28
- # Thread ID: 15995640
29
- # Fiber ID: 38731780
30
- # Total: 66.716394
31
- # Sort by: self_time
32
-
33
- # %self total self wait child calls name
34
- # 54.73 49.718 36.513 0.000 13.205 57084873 Timers::Timer#<=>
35
- # 23.74 65.559 15.841 0.000 49.718 32534 Array#sort!
36
- # 19.79 13.205 13.205 0.000 0.000 57084873 Float#<=>
37
-
38
- # Max out events performance (on my computer):
39
- # Serviced 1142649 events in 11.194903921 seconds, 102068.70405115146 e/s.
40
-
41
- RSpec.describe Timers::Group do
42
- it "runs efficiently" do
43
- result = []
44
- range = (1..500)
45
- duration = 2.0
46
-
47
- total = 0
48
- range.each do |index|
49
- offset = index.to_f / range.max
50
- total += (duration / offset).floor
51
-
52
- subject.every(index.to_f / range.max, :strict) { result << index }
53
- end
54
-
55
- subject.wait while result.size < total
56
-
57
- rate = result.size.to_f / subject.current_offset
58
- puts "Serviced #{result.size} events in #{subject.current_offset} seconds, #{rate} e/s."
59
-
60
- expect(subject.current_offset).to be_within(TIMER_QUANTUM).of(duration)
61
- end
62
-
63
- # it "runs efficiently at high volume" do
64
- # results = []
65
- # range = (1..300)
66
- # groups = (1..20)
67
- # duration = 101
68
- #
69
- # timers = []
70
- # @mutex = Mutex.new
71
- # start = Time.now
72
- # groups.each do |gi|
73
- # timers << Thread.new {
74
- # result = []
75
- # timer = Timers::Group.new
76
- # total = 0
77
- # range.each do |ri|
78
- # offset = ri.to_f / range.max
79
- # total += (duration / offset).floor
80
- # timer.every(ri.to_f / range.max, :strict) { result << ri }
81
- # end
82
- # timer.wait while result.size < total
83
- # @mutex.synchronize { results += result }
84
- #
85
- # }
86
- # end
87
- # timers.each { |t| t.join }
88
- # finish = Time.now
89
- #
90
- # rate = results.size.to_f / ( runtime = finish - start )
91
- #
92
- # puts "Serviced #{results.size} events in #{runtime} seconds, #{rate} e/s; across #{groups.max} timers."
93
- #
94
- # expect(runtime).to be_within(TIMER_QUANTUM).of(duration)
95
- # end
96
- end