timers 4.1.1 → 4.1.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.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.rubocop.yml +28 -0
- data/.ruby-version +1 -0
- data/.travis.yml +13 -10
- data/CHANGES.md +31 -23
- data/Gemfile +16 -3
- data/LICENSE +1 -1
- data/README.md +27 -17
- data/Rakefile +6 -3
- data/lib/timers.rb +4 -3
- data/lib/timers/events.rb +34 -39
- data/lib/timers/group.rb +30 -35
- data/lib/timers/timer.rb +25 -24
- data/lib/timers/version.rb +3 -1
- data/lib/timers/wait.rb +17 -18
- data/spec/spec_helper.rb +5 -3
- data/spec/{cancel_spec.rb → timers/cancel_spec.rb} +12 -13
- data/spec/{events_spec.rb → timers/events_spec.rb} +20 -21
- data/spec/{every_spec.rb → timers/every_spec.rb} +1 -2
- data/spec/{group_spec.rb → timers/group_spec.rb} +19 -18
- data/spec/{performance_spec.rb → timers/performance_spec.rb} +38 -42
- data/spec/timers/strict_spec.rb +36 -0
- data/spec/{timeout_spec.rb → timers/wait_spec.rb} +11 -10
- data/timers.gemspec +16 -13
- metadata +29 -41
- data/spec/strict_spec.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97c81b8ed305099faee9ecec3ee32f6960b70d54
|
4
|
+
data.tar.gz: 90d94a796bfe60e78963b0053648396aefdb19b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbea5311bcd5fb7bfe7c98191ac15146647b91ab5c994309f3bc14fe394ac97832361afa6ff7f257d844a802265125a5bafa051026fa1eed979f8310d8a21f87
|
7
|
+
data.tar.gz: 2097c9e9d6e838550fa3c4735db828173852dd5e598670a376a04de132274df6464687cfe0e72992c2469d5d355932808fe1147e44ec5f26e2162046267c37ad
|
data/.rspec
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
AllCops:
|
2
|
+
DisplayCopNames: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# Style
|
6
|
+
#
|
7
|
+
|
8
|
+
LineLength:
|
9
|
+
Max: 128
|
10
|
+
|
11
|
+
Style/NumericPredicate:
|
12
|
+
Enabled: false
|
13
|
+
|
14
|
+
Style/SafeNavigation:
|
15
|
+
Enabled: false
|
16
|
+
|
17
|
+
Style/StringLiterals:
|
18
|
+
EnforcedStyle: double_quotes
|
19
|
+
|
20
|
+
#
|
21
|
+
# Metrics
|
22
|
+
#
|
23
|
+
|
24
|
+
Metrics/ClassLength:
|
25
|
+
Max: 100
|
26
|
+
|
27
|
+
Metrics/MethodLength:
|
28
|
+
Max: 25
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.3
|
data/.travis.yml
CHANGED
@@ -1,18 +1,21 @@
|
|
1
|
+
language: ruby
|
2
|
+
sudo: false
|
3
|
+
|
4
|
+
bundler_args: --without development doc
|
5
|
+
|
1
6
|
rvm:
|
2
|
-
- 1.9.3
|
3
7
|
- 2.0.0
|
4
|
-
- 2.1.
|
5
|
-
-
|
6
|
-
-
|
7
|
-
- jruby-
|
8
|
-
- rbx-2
|
8
|
+
- 2.1.10
|
9
|
+
- 2.2.6
|
10
|
+
- 2.3.3
|
11
|
+
- jruby-9.1.6.0
|
9
12
|
|
10
13
|
matrix:
|
11
14
|
fast_finish: true
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
-
|
15
|
+
|
16
|
+
branches:
|
17
|
+
only:
|
18
|
+
- master
|
16
19
|
|
17
20
|
notifications:
|
18
21
|
irc: "irc.freenode.org#celluloid"
|
data/CHANGES.md
CHANGED
@@ -1,54 +1,62 @@
|
|
1
|
-
4.1.
|
2
|
-
|
1
|
+
## 4.1.2 (2016-11-26)
|
2
|
+
|
3
|
+
* RuboCop reformatting
|
4
|
+
|
5
|
+
## 4.1.1 (2015-08-21)
|
6
|
+
|
3
7
|
* Remove `RubyProf` from Gemfile and a test, due to it providing no substantial benefit while increasing problems building bundles under Rubinius.
|
4
8
|
|
5
|
-
4.1.0 (2015-08-16)
|
6
|
-
|
9
|
+
## 4.1.0 (2015-08-16)
|
10
|
+
|
7
11
|
* Addition of `now_and_every` method; fires block immediately, then sets recurring timer.
|
8
12
|
* Includes `now_and_after` method; does the same as above for one-shot timers: essentially a "two-shot" timer.
|
9
13
|
|
10
|
-
4.0.
|
11
|
-
|
14
|
+
# 4.0.4 (2015-09-01)
|
15
|
+
|
16
|
+
* Re-release of the `4.1.1` version under the `4.0.4` designation to work-around issues caused by yanking `4.0.2` a couple weeks ago.
|
17
|
+
|
18
|
+
## 4.0.1 (2014-09-10)
|
19
|
+
|
12
20
|
* Memory leak fixes
|
13
21
|
* mathn fix for those crazy enough to use it
|
14
22
|
|
15
|
-
4.0.0 (2014-07-27)
|
16
|
-
|
23
|
+
## 4.0.0 (2014-07-27)
|
24
|
+
|
17
25
|
* Replace Timers::Timeout with Timers::Wait
|
18
|
-
* Timers::Group#wait_interval now returns nil when no timers, a
|
26
|
+
* Timers::Group#wait_interval now returns nil when no timers, a positive or
|
19
27
|
negative interval which if positive is the amount of time required to wait
|
20
28
|
and if negative, how far in the past the latest timer should have fired
|
21
29
|
* Performance improvements
|
22
30
|
|
23
|
-
3.0.1 (2014-06-27)
|
24
|
-
|
31
|
+
## 3.0.1 (2014-06-27)
|
32
|
+
|
25
33
|
* Require 'set' automatically
|
26
34
|
|
27
|
-
3.0.0 (2014-06-14)
|
28
|
-
|
35
|
+
# 3.0.0 (2014-06-14)
|
36
|
+
|
29
37
|
* Refactor `Timers` class into `Timers::Group`
|
30
38
|
* Add `Timers::Timeout` class for implementing timeouts
|
31
39
|
* Fix timer fudging
|
32
40
|
* Update to RSpec 3
|
33
41
|
|
34
|
-
2.0.0 (2013-12-30)
|
35
|
-
|
42
|
+
## 2.0.0 (2013-12-30)
|
43
|
+
|
36
44
|
* Switch to Hitimes for high precision monotonic counters
|
37
45
|
* Removed Timers#time. Replaced with Timers#current_offset which provides a
|
38
46
|
monotonic time counter.
|
39
47
|
|
40
|
-
1.1.0
|
41
|
-
|
48
|
+
## 1.1.0
|
49
|
+
|
42
50
|
* Timers#after_milliseconds and #after_ms for waiting in milliseconds
|
43
51
|
|
44
|
-
1.0.2
|
45
|
-
|
52
|
+
## 1.0.2
|
53
|
+
|
46
54
|
* Handle overdue timers correctly
|
47
55
|
|
48
|
-
1.0.1
|
49
|
-
|
56
|
+
## 1.0.1
|
57
|
+
|
50
58
|
* Explicitly require Forwardable from stdlib
|
51
59
|
|
52
|
-
1.0.0
|
53
|
-
|
60
|
+
## 1.0.0
|
61
|
+
|
54
62
|
* Initial release
|
data/Gemfile
CHANGED
@@ -1,6 +1,19 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
source "https://rubygems.org"
|
4
4
|
|
5
|
-
# Specify your gem's dependencies in timers.gemspec
|
6
5
|
gemspec
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "pry", require: false
|
9
|
+
end
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem "rspec", "~> 3", require: false
|
13
|
+
gem "rubocop", "0.45.0", require: false
|
14
|
+
gem "coveralls", require: false
|
15
|
+
end
|
16
|
+
|
17
|
+
group :development, :test do
|
18
|
+
gem "rake"
|
19
|
+
end
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,20 +1,31 @@
|
|
1
|
-
Timers
|
2
|
-
======
|
3
|
-
[](http://rubygems.org/gems/timers)
|
4
|
-
[](http://travis-ci.org/celluloid/timers)
|
5
|
-
[](https://codeclimate.com/github/celluloid/timers)
|
6
|
-
[](https://coveralls.io/r/celluloid/timers)
|
1
|
+
# Timers for Ruby [![Gem Version][gem-image]][gem-link] [![Build Status][build-image]][build-link] [![Code Climate][codeclimate-image]][codeclimate-link] [![Coverage Status][coverage-image]][coverage-link] [![MIT licensed][license-image]][license-link]
|
7
2
|
|
8
|
-
|
9
|
-
|
3
|
+
[gem-image]: https://badge.fury.io/rb/timers.svg
|
4
|
+
[gem-link]: http://rubygems.org/gems/timers
|
5
|
+
[build-image]: https://secure.travis-ci.org/celluloid/timers.svg?branch=master
|
6
|
+
[build-link]: https://travis-ci.org/celluloid/timers
|
7
|
+
[codeclimate-image]: https://codeclimate.com/github/celluloid/timers.svg
|
8
|
+
[codeclimate-link]: https://codeclimate.com/github/celluloid/timers
|
9
|
+
[coverage-image]: https://coveralls.io/repos/celluloid/timers/badge.svg?branch=master
|
10
|
+
[coverage-link]: https://coveralls.io/r/celluloid/timers
|
11
|
+
[license-image]: https://img.shields.io/badge/license-MIT-blue.svg
|
12
|
+
[license-link]: https://github.com/celluloid/timers/master/LICENSE.txt
|
10
13
|
|
11
|
-
|
12
|
-
single timeout but you want to run multiple timers on top of it. An example of
|
13
|
-
such a library is [nio4r](https://github.com/celluloid/nio4r), a cross-platform
|
14
|
-
Ruby library for using system calls like epoll and kqueue.
|
14
|
+
Collections of one-shot and periodic timers, intended for use with event loops.
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
**Does not require Celluloid!** Though this gem was originally written
|
17
|
+
to provide the timer subsystem for [Celluloid], it can be used independently
|
18
|
+
in any sort of event loop context, or can provide a purely timer-based event
|
19
|
+
loop itself.
|
20
|
+
|
21
|
+
[Celluloid]: https://github.com/celluloid/celluloid/
|
22
|
+
|
23
|
+
## Supported platforms
|
24
|
+
|
25
|
+
* Ruby 2.0, 2.1, 2.2, and 2.3
|
26
|
+
* JRuby 9000
|
27
|
+
|
28
|
+
## Usage
|
18
29
|
|
19
30
|
Create a new timer group with `Timers::Group.new`:
|
20
31
|
|
@@ -94,10 +105,9 @@ timers.resume
|
|
94
105
|
10.times { timers.wait } # will fire all timers
|
95
106
|
```
|
96
107
|
|
97
|
-
License
|
98
|
-
-------
|
108
|
+
## License
|
99
109
|
|
100
|
-
Copyright (c)
|
110
|
+
Copyright (c) 2012-2016 Celluloid timers project developers (given in the file
|
101
111
|
AUTHORS.md).
|
102
112
|
|
103
113
|
Distributed under the MIT License. See LICENSE file for further details.
|
data/Rakefile
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
require "bundler/gem_tasks"
|
3
|
-
require 'rspec/core/rake_task'
|
4
3
|
|
4
|
+
require "rspec/core/rake_task"
|
5
5
|
RSpec::Core::RakeTask.new
|
6
6
|
|
7
|
-
|
7
|
+
require "rubocop/rake_task"
|
8
|
+
RuboCop::RakeTask.new
|
9
|
+
|
10
|
+
task default: %w(spec rubocop)
|
data/lib/timers.rb
CHANGED
data/lib/timers/events.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
|
-
require
|
3
|
-
require
|
3
|
+
require "forwardable"
|
4
|
+
require "hitimes"
|
4
5
|
|
5
|
-
require
|
6
|
+
require "timers/timer"
|
6
7
|
|
7
8
|
module Timers
|
8
9
|
# Maintains an ordered list of events, which can be cancelled.
|
@@ -13,73 +14,67 @@ module Timers
|
|
13
14
|
@time = time
|
14
15
|
@callback = callback
|
15
16
|
end
|
16
|
-
|
17
|
+
|
17
18
|
# The absolute time that the handle should be fired at.
|
18
|
-
|
19
|
-
|
19
|
+
attr_reader :time
|
20
|
+
|
20
21
|
# Cancel this timer, O(1).
|
21
22
|
def cancel!
|
22
23
|
# The simplest way to keep track of cancelled status is to nullify the
|
23
24
|
# callback. This should also be optimal for garbage collection.
|
24
25
|
@callback = nil
|
25
26
|
end
|
26
|
-
|
27
|
+
|
27
28
|
# Has this timer been cancelled? Cancelled timer's don't fire.
|
28
29
|
def cancelled?
|
29
30
|
@callback.nil?
|
30
31
|
end
|
31
|
-
|
32
|
-
def >
|
32
|
+
|
33
|
+
def >(other)
|
33
34
|
@time > other.to_f
|
34
35
|
end
|
35
|
-
|
36
|
+
|
36
37
|
def to_f
|
37
38
|
@time
|
38
39
|
end
|
39
|
-
|
40
|
+
|
40
41
|
# Fire the callback if not cancelled with the given time parameter.
|
41
42
|
def fire(time)
|
42
|
-
if @callback
|
43
|
-
@callback.call(time)
|
44
|
-
end
|
43
|
+
@callback.call(time) if @callback
|
45
44
|
end
|
46
45
|
end
|
47
|
-
|
46
|
+
|
48
47
|
def initialize
|
49
48
|
# A sequence of handles, maintained in sorted order, future to present.
|
50
49
|
# @sequence.last is the next event to be fired.
|
51
50
|
@sequence = []
|
52
51
|
end
|
53
|
-
|
52
|
+
|
54
53
|
# Add an event at the given time.
|
55
54
|
def schedule(time, callback)
|
56
55
|
handle = Handle.new(time.to_f, callback)
|
57
|
-
|
56
|
+
|
58
57
|
index = bisect_left(@sequence, handle)
|
59
|
-
|
58
|
+
|
60
59
|
# Maintain sorted order, O(logN) insertion time.
|
61
60
|
@sequence.insert(index, handle)
|
62
|
-
|
63
|
-
|
61
|
+
|
62
|
+
handle
|
64
63
|
end
|
65
|
-
|
64
|
+
|
66
65
|
# Returns the first non-cancelled handle.
|
67
66
|
def first
|
68
|
-
while handle = @sequence.last
|
69
|
-
|
70
|
-
|
71
|
-
else
|
72
|
-
return handle
|
73
|
-
end
|
67
|
+
while (handle = @sequence.last)
|
68
|
+
return handle unless handle.cancelled?
|
69
|
+
@sequence.pop
|
74
70
|
end
|
75
|
-
# @sequence.reverse.find { |handle| !handle.cancelled? }
|
76
71
|
end
|
77
|
-
|
72
|
+
|
78
73
|
# Returns the number of pending (possibly cancelled) events.
|
79
74
|
def size
|
80
75
|
@sequence.size
|
81
76
|
end
|
82
|
-
|
77
|
+
|
83
78
|
# Fire all handles for which Handle#time is less than the given time.
|
84
79
|
def fire(time)
|
85
80
|
pop(time).reverse_each do |handle|
|
@@ -89,28 +84,28 @@ module Timers
|
|
89
84
|
|
90
85
|
private
|
91
86
|
|
92
|
-
# Efficiently take k handles for which Handle#time is less than the given
|
87
|
+
# Efficiently take k handles for which Handle#time is less than the given
|
93
88
|
# time.
|
94
89
|
def pop(time)
|
95
90
|
index = bisect_left(@sequence, time)
|
96
|
-
|
91
|
+
|
97
92
|
@sequence.pop(@sequence.size - index)
|
98
93
|
end
|
99
|
-
|
100
|
-
# Return the left-most index where to insert item e, in a list a, assuming
|
94
|
+
|
95
|
+
# Return the left-most index where to insert item e, in a list a, assuming
|
101
96
|
# a is sorted in descending order.
|
102
97
|
def bisect_left(a, e, l = 0, u = a.length)
|
103
98
|
while l < u
|
104
|
-
m = l + (u-l).div(2)
|
105
|
-
|
99
|
+
m = l + (u - l).div(2)
|
100
|
+
|
106
101
|
if a[m] > e
|
107
|
-
l = m+1
|
102
|
+
l = m + 1
|
108
103
|
else
|
109
104
|
u = m
|
110
105
|
end
|
111
106
|
end
|
112
|
-
|
113
|
-
|
107
|
+
|
108
|
+
l
|
114
109
|
end
|
115
110
|
end
|
116
111
|
end
|
data/lib/timers/group.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "set"
|
4
|
+
require "forwardable"
|
5
|
+
require "hitimes"
|
5
6
|
|
6
|
-
require
|
7
|
-
require
|
7
|
+
require "timers/timer"
|
8
|
+
require "timers/events"
|
8
9
|
|
9
10
|
module Timers
|
11
|
+
# A collection of timers which may fire at different times
|
10
12
|
class Group
|
11
13
|
include Enumerable
|
12
14
|
|
@@ -15,22 +17,22 @@ module Timers
|
|
15
17
|
|
16
18
|
def initialize
|
17
19
|
@events = Events.new
|
18
|
-
|
20
|
+
|
19
21
|
@timers = Set.new
|
20
22
|
@paused_timers = Set.new
|
21
|
-
|
23
|
+
|
22
24
|
@interval = Hitimes::Interval.new
|
23
25
|
@interval.start
|
24
26
|
end
|
25
27
|
|
26
28
|
# Scheduled events:
|
27
|
-
|
28
|
-
|
29
|
+
attr_reader :events
|
30
|
+
|
29
31
|
# Active timers:
|
30
|
-
|
31
|
-
|
32
|
+
attr_reader :timers
|
33
|
+
|
32
34
|
# Paused timers:
|
33
|
-
|
35
|
+
attr_reader :paused_timers
|
34
36
|
|
35
37
|
# Call the given block after the given interval. The first argument will be
|
36
38
|
# the time at which the group was asked to fire timers for.
|
@@ -41,11 +43,11 @@ module Timers
|
|
41
43
|
# Call the given block immediately, and then after the given interval. The first
|
42
44
|
# argument will be the time at which the group was asked to fire timers for.
|
43
45
|
def now_and_after(interval, &block)
|
44
|
-
|
46
|
+
yield
|
45
47
|
after(interval, &block)
|
46
48
|
end
|
47
49
|
|
48
|
-
# Call the given block periodically at the given interval. The first
|
50
|
+
# Call the given block periodically at the given interval. The first
|
49
51
|
# argument will be the time at which the group was asked to fire timers for.
|
50
52
|
def every(interval, recur = true, &block)
|
51
53
|
Timer.new(self, interval, recur, &block)
|
@@ -54,28 +56,28 @@ module Timers
|
|
54
56
|
# Call the given block immediately, and then periodically at the given interval. The first
|
55
57
|
# argument will be the time at which the group was asked to fire timers for.
|
56
58
|
def now_and_every(interval, recur = true, &block)
|
57
|
-
|
59
|
+
yield
|
58
60
|
every(interval, recur, &block)
|
59
61
|
end
|
60
62
|
|
61
63
|
# Wait for the next timer and fire it. Can take a block, which should behave
|
62
64
|
# like sleep(n), except that n may be nil (sleep forever) or a negative
|
63
65
|
# number (fire immediately after return).
|
64
|
-
def wait
|
66
|
+
def wait
|
65
67
|
if block_given?
|
66
68
|
yield wait_interval
|
67
|
-
|
68
|
-
while interval = wait_interval
|
69
|
+
|
70
|
+
while (interval = wait_interval) && interval > 0
|
69
71
|
yield interval
|
70
72
|
end
|
71
73
|
else
|
72
|
-
while interval = wait_interval
|
74
|
+
while (interval = wait_interval) && interval > 0
|
73
75
|
# We cannot assume that sleep will wait for the specified time, it might be +/- a bit.
|
74
76
|
sleep interval
|
75
77
|
end
|
76
78
|
end
|
77
79
|
|
78
|
-
|
80
|
+
fire
|
79
81
|
end
|
80
82
|
|
81
83
|
# Interval to wait until when the next timer will fire.
|
@@ -83,32 +85,27 @@ module Timers
|
|
83
85
|
# - -ve: timers expired already
|
84
86
|
# - 0: timers ready to fire
|
85
87
|
# - +ve: timers waiting to fire
|
86
|
-
def wait_interval(offset =
|
87
|
-
|
88
|
-
|
89
|
-
end
|
88
|
+
def wait_interval(offset = current_offset)
|
89
|
+
handle = @events.first
|
90
|
+
handle.time - Float(offset) if handle
|
90
91
|
end
|
91
92
|
|
92
93
|
# Fire all timers that are ready.
|
93
|
-
def fire(offset =
|
94
|
+
def fire(offset = current_offset)
|
94
95
|
@events.fire(offset)
|
95
96
|
end
|
96
97
|
|
97
98
|
# Pause all timers.
|
98
99
|
def pause
|
99
|
-
@timers.dup.each
|
100
|
-
timer.pause
|
101
|
-
end
|
100
|
+
@timers.dup.each(&:pause)
|
102
101
|
end
|
103
102
|
|
104
103
|
# Resume all timers.
|
105
104
|
def resume
|
106
|
-
@paused_timers.dup.each
|
107
|
-
timer.resume
|
108
|
-
end
|
105
|
+
@paused_timers.dup.each(&:resume)
|
109
106
|
end
|
110
107
|
|
111
|
-
|
108
|
+
alias continue resume
|
112
109
|
|
113
110
|
# Delay all timers.
|
114
111
|
def delay(seconds)
|
@@ -119,9 +116,7 @@ module Timers
|
|
119
116
|
|
120
117
|
# Cancel all timers.
|
121
118
|
def cancel
|
122
|
-
@timers.dup.each
|
123
|
-
timer.cancel
|
124
|
-
end
|
119
|
+
@timers.dup.each(&:cancel)
|
125
120
|
end
|
126
121
|
|
127
122
|
# The group's current time.
|