timers 0.0.0 → 1.0.0.pre
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/.travis.yml +3 -5
- data/lib/timers.rb +17 -46
- data/lib/timers/version.rb +1 -1
- data/spec/timers_spec.rb +7 -7
- metadata +9 -9
data/.travis.yml
CHANGED
data/lib/timers.rb
CHANGED
@@ -1,27 +1,30 @@
|
|
1
|
-
require
|
1
|
+
require 'set'
|
2
|
+
require 'timers/version'
|
2
3
|
|
3
4
|
# Low precision timers implemented in pure Ruby
|
4
5
|
class Timers
|
6
|
+
extend Forwardable
|
7
|
+
include Enumerable
|
8
|
+
def_delegators :@timers, :add, :delete, :each, :empty?
|
9
|
+
|
5
10
|
def initialize
|
6
|
-
@timers =
|
11
|
+
@timers = SortedSet.new
|
7
12
|
end
|
8
13
|
|
9
14
|
# Call the given block after the given interval
|
10
15
|
def after(interval, &block)
|
11
|
-
Timer.new(self, interval, false, block)
|
16
|
+
Timer.new(self, interval, false, &block)
|
12
17
|
end
|
13
18
|
|
14
19
|
# Call the given block periodically at the given interval
|
15
20
|
def every(interval, &block)
|
16
|
-
Timer.new(self, interval, true, block)
|
21
|
+
Timer.new(self, interval, true, &block)
|
17
22
|
end
|
18
23
|
|
19
24
|
# Wait for the next timer and fire it
|
20
25
|
def wait
|
21
26
|
return if @timers.empty?
|
22
|
-
|
23
|
-
interval = wait_interval
|
24
|
-
sleep interval if interval >= Timer::QUANTUM
|
27
|
+
sleep wait_interval
|
25
28
|
fire
|
26
29
|
end
|
27
30
|
|
@@ -34,55 +37,23 @@ class Timers
|
|
34
37
|
def fire
|
35
38
|
return if @timers.empty?
|
36
39
|
|
37
|
-
time = Time.now +
|
38
|
-
while not empty? and time
|
39
|
-
timer = @timers.
|
40
|
+
time = Time.now + 0.001
|
41
|
+
while not empty? and time >= @timers.first.time
|
42
|
+
timer = @timers.first
|
43
|
+
@timers.delete timer
|
40
44
|
timer.call
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
44
|
-
|
45
|
-
|
46
|
-
@timers.insert(index(timer), timer)
|
47
|
-
end
|
48
|
-
|
49
|
-
# Remove a given timer from the set we're monitoring
|
50
|
-
def cancel(timer)
|
51
|
-
@timers.delete timer
|
52
|
-
end
|
53
|
-
|
54
|
-
# Are there any timers pending?
|
55
|
-
def empty?
|
56
|
-
@timers.empty?
|
57
|
-
end
|
58
|
-
|
59
|
-
# Index where a timer would be located in the sorted timers array
|
60
|
-
def index(timer)
|
61
|
-
l, r = 0, @timers.size - 1
|
62
|
-
|
63
|
-
while l <= r
|
64
|
-
m = (r + l) / 2
|
65
|
-
if timer < @timers.at(m)
|
66
|
-
r = m - 1
|
67
|
-
else
|
68
|
-
l = m + 1
|
69
|
-
end
|
70
|
-
end
|
71
|
-
l
|
72
|
-
end
|
48
|
+
alias_method :insert, :add
|
49
|
+
alias_method :cancel, :delete
|
73
50
|
|
74
51
|
# An individual timer set to fire a given proc at a given time
|
75
52
|
class Timer
|
76
53
|
include Comparable
|
77
|
-
|
78
|
-
# The timer system is guaranteed (at least by the specs) to be this precise
|
79
|
-
# during normal operation. Long blocking calls within actors will delay the
|
80
|
-
# firing of timers
|
81
|
-
QUANTUM = 0.02
|
82
|
-
|
83
54
|
attr_reader :interval, :time, :recurring
|
84
55
|
|
85
|
-
def initialize(timers, interval, recurring, block)
|
56
|
+
def initialize(timers, interval, recurring = false, &block)
|
86
57
|
@timers, @interval, @recurring = timers, interval, recurring
|
87
58
|
@block = block
|
88
59
|
|
data/lib/timers/version.rb
CHANGED
data/spec/timers_spec.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Timers do
|
4
|
-
|
4
|
+
# Level of accuracy enforced by the tests (50ms)
|
5
|
+
Q = 0.05
|
5
6
|
|
6
7
|
it "sleeps until the next timer" do
|
7
|
-
interval
|
8
|
+
interval = Q * 2
|
8
9
|
started_at = Time.now
|
9
10
|
|
10
11
|
fired = false
|
@@ -15,7 +16,7 @@ describe Timers do
|
|
15
16
|
(Time.now - started_at).should be_within(Q).of interval
|
16
17
|
end
|
17
18
|
|
18
|
-
it "
|
19
|
+
it "calculates the interval until the next timer should fire" do
|
19
20
|
interval = 0.1
|
20
21
|
|
21
22
|
subject.after(interval)
|
@@ -36,17 +37,16 @@ describe Timers do
|
|
36
37
|
end
|
37
38
|
|
38
39
|
describe "recurring timers" do
|
39
|
-
it "
|
40
|
+
it "continues to fire the timers at each interval" do
|
40
41
|
result = []
|
41
42
|
|
42
|
-
subject.every(Q *
|
43
|
+
subject.every(Q * 2) { result << :foo }
|
43
44
|
|
44
45
|
sleep Q * 3
|
45
46
|
subject.fire
|
46
47
|
result.should == [:foo]
|
47
48
|
|
48
|
-
sleep Q *
|
49
|
-
subject.fire
|
49
|
+
sleep Q * 5
|
50
50
|
subject.fire
|
51
51
|
result.should == [:foo, :foo]
|
52
52
|
end
|
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0.pre
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Tony Arcieri
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &70102019350080 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70102019350080
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &70102019349180 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70102019349180
|
36
36
|
description: Pure Ruby one-shot and periodic timers
|
37
37
|
email:
|
38
38
|
- tony.arcieri@gmail.com
|
@@ -67,9 +67,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
67
67
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
68
|
none: false
|
69
69
|
requirements:
|
70
|
-
- - ! '
|
70
|
+
- - ! '>'
|
71
71
|
- !ruby/object:Gem::Version
|
72
|
-
version:
|
72
|
+
version: 1.3.1
|
73
73
|
requirements: []
|
74
74
|
rubyforge_project:
|
75
75
|
rubygems_version: 1.8.10
|