timers 4.1.2 → 4.3.2

Sign up to get free protection for your applications and to get access to all the features.
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