timers 4.1.2 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 97c81b8ed305099faee9ecec3ee32f6960b70d54
4
- data.tar.gz: 90d94a796bfe60e78963b0053648396aefdb19b6
2
+ SHA256:
3
+ metadata.gz: e1665f074c230a801e0eb6648214a6d0248d4baada8da1f4e60abd0983bba517
4
+ data.tar.gz: de4eac12ecba1826d6ae5ef1d6958a451595b1a9e8e54dba7f1718d7f15182dd
5
5
  SHA512:
6
- metadata.gz: dbea5311bcd5fb7bfe7c98191ac15146647b91ab5c994309f3bc14fe394ac97832361afa6ff7f257d844a802265125a5bafa051026fa1eed979f8310d8a21f87
7
- data.tar.gz: 2097c9e9d6e838550fa3c4735db828173852dd5e598670a376a04de132274df6464687cfe0e72992c2469d5d355932808fe1147e44ec5f26e2162046267c37ad
6
+ metadata.gz: c0e005f02975d324b7fbe7d8e284a2d5318be78352e129ce00abf20594d3e6a18b30103e1137b2d9fe91bd5a2251e7b22fb5cdc255f5153f219bf90bd3b6160d
7
+ data.tar.gz: 64210a85d0a8efe2540d9ee6da050c5d8298a5332bd2ba14758bd784a7f991ad40b1f828b47320525ab025249859ca6419f172421492fe6ced56a76e34820541
data/.rspec CHANGED
@@ -1,6 +1,3 @@
1
- --color
2
1
  --format documentation
3
- --backtrace
4
- --order random
5
2
  --warnings
6
- --require spec_helper
3
+ --require spec_helper
@@ -1,21 +1,19 @@
1
1
  language: ruby
2
2
  sudo: false
3
-
4
- bundler_args: --without development doc
5
-
6
- rvm:
7
- - 2.0.0
8
- - 2.1.10
9
- - 2.2.6
10
- - 2.3.3
11
- - jruby-9.1.6.0
3
+ dist: xenial
4
+ cache: bundler
12
5
 
13
6
  matrix:
14
- fast_finish: true
15
-
16
- branches:
17
- only:
18
- - master
19
-
20
- notifications:
21
- irc: "irc.freenode.org#celluloid"
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 CHANGED
@@ -1,19 +1,15 @@
1
- # frozen_string_literal: true
2
-
3
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
4
2
 
5
3
  gemspec
6
4
 
7
5
  group :development do
8
- gem "pry", require: false
6
+ gem 'pry'
9
7
  end
10
8
 
11
9
  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"
10
+ gem 'benchmark-ips'
11
+ gem "ruby-prof", platform: :mri
12
+
13
+ gem 'simplecov'
14
+ gem 'coveralls'
19
15
  end
data/README.md CHANGED
@@ -1,29 +1,28 @@
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]
1
+ # Timers
2
2
 
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
3
+ Collections of one-shot and periodic timers, intended for use with event loops such as [async].
13
4
 
14
- Collections of one-shot and periodic timers, intended for use with event loops.
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)
15
8
 
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.
9
+ [async]: https://github.com/socketry/async
20
10
 
21
- [Celluloid]: https://github.com/celluloid/celluloid/
11
+ ## Installation
22
12
 
23
- ## Supported platforms
13
+ Add this line to your application's Gemfile:
24
14
 
25
- * Ruby 2.0, 2.1, 2.2, and 2.3
26
- * JRuby 9000
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
27
26
 
28
27
  ## Usage
29
28
 
@@ -105,9 +104,46 @@ timers.resume
105
104
  10.times { timers.wait } # will fire all timers
106
105
  ```
107
106
 
108
- ## License
107
+ ## Contributing
109
108
 
110
- Copyright (c) 2012-2016 Celluloid timers project developers (given in the file
111
- AUTHORS.md).
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
112
116
 
113
- Distributed under the MIT License. See LICENSE file for further details.
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 CHANGED
@@ -1,10 +1,6 @@
1
- # frozen_string_literal: true
2
1
  require "bundler/gem_tasks"
3
-
4
2
  require "rspec/core/rake_task"
5
- RSpec::Core::RakeTask.new
6
3
 
7
- require "rubocop/rake_task"
8
- RuboCop::RakeTask.new
4
+ RSpec::Core::RakeTask.new(:test)
9
5
 
10
- task default: %w(spec rubocop)
6
+ task :default => :test
@@ -1,4 +1,9 @@
1
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
+ #
2
7
 
3
8
  require "timers/version"
4
9
 
@@ -1,111 +1,113 @@
1
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
+ #
2
7
 
3
- require "forwardable"
4
- require "hitimes"
5
-
6
- require "timers/timer"
8
+ require_relative "timer"
7
9
 
8
10
  module Timers
9
- # Maintains an ordered list of events, which can be cancelled.
10
- class Events
11
- # Represents a cancellable handle for a specific timer event.
12
- class Handle
13
- def initialize(time, callback)
14
- @time = time
15
- @callback = callback
16
- end
17
-
18
- # The absolute time that the handle should be fired at.
19
- attr_reader :time
20
-
21
- # Cancel this timer, O(1).
22
- def cancel!
23
- # The simplest way to keep track of cancelled status is to nullify the
24
- # callback. This should also be optimal for garbage collection.
25
- @callback = nil
26
- end
27
-
28
- # Has this timer been cancelled? Cancelled timer's don't fire.
29
- def cancelled?
30
- @callback.nil?
31
- end
32
-
33
- def >(other)
34
- @time > other.to_f
35
- end
36
-
37
- def to_f
38
- @time
39
- end
40
-
41
- # Fire the callback if not cancelled with the given time parameter.
42
- def fire(time)
43
- @callback.call(time) if @callback
44
- end
45
- end
46
-
47
- def initialize
48
- # A sequence of handles, maintained in sorted order, future to present.
49
- # @sequence.last is the next event to be fired.
50
- @sequence = []
51
- end
52
-
53
- # Add an event at the given time.
54
- def schedule(time, callback)
55
- handle = Handle.new(time.to_f, callback)
56
-
57
- index = bisect_left(@sequence, handle)
58
-
59
- # Maintain sorted order, O(logN) insertion time.
60
- @sequence.insert(index, handle)
61
-
62
- handle
63
- end
64
-
65
- # Returns the first non-cancelled handle.
66
- def first
67
- while (handle = @sequence.last)
68
- return handle unless handle.cancelled?
69
- @sequence.pop
70
- end
71
- end
72
-
73
- # Returns the number of pending (possibly cancelled) events.
74
- def size
75
- @sequence.size
76
- end
77
-
78
- # Fire all handles for which Handle#time is less than the given time.
79
- def fire(time)
80
- pop(time).reverse_each do |handle|
81
- handle.fire(time)
82
- end
83
- end
84
-
85
- private
86
-
87
- # Efficiently take k handles for which Handle#time is less than the given
88
- # time.
89
- def pop(time)
90
- index = bisect_left(@sequence, time)
91
-
92
- @sequence.pop(@sequence.size - index)
93
- end
94
-
95
- # Return the left-most index where to insert item e, in a list a, assuming
96
- # a is sorted in descending order.
97
- def bisect_left(a, e, l = 0, u = a.length)
98
- while l < u
99
- m = l + (u - l).div(2)
100
-
101
- if a[m] > e
102
- l = m + 1
103
- else
104
- u = m
105
- end
106
- end
107
-
108
- l
109
- end
110
- end
11
+ # Maintains an ordered list of events, which can be cancelled.
12
+ class Events
13
+ # Represents a cancellable handle for a specific timer event.
14
+ class Handle
15
+ def initialize(time, callback)
16
+ @time = time
17
+ @callback = callback
18
+ end
19
+
20
+ # The absolute time that the handle should be fired at.
21
+ attr_reader :time
22
+
23
+ # Cancel this timer, O(1).
24
+ def cancel!
25
+ # The simplest way to keep track of cancelled status is to nullify the
26
+ # callback. This should also be optimal for garbage collection.
27
+ @callback = nil
28
+ end
29
+
30
+ # Has this timer been cancelled? Cancelled timer's don't fire.
31
+ def cancelled?
32
+ @callback.nil?
33
+ end
34
+
35
+ def >(other)
36
+ @time > other.to_f
37
+ end
38
+
39
+ def to_f
40
+ @time
41
+ end
42
+
43
+ # Fire the callback if not cancelled with the given time parameter.
44
+ def fire(time)
45
+ @callback.call(time) if @callback
46
+ end
47
+ end
48
+
49
+ def initialize
50
+ # A sequence of handles, maintained in sorted order, future to present.
51
+ # @sequence.last is the next event to be fired.
52
+ @sequence = []
53
+ end
54
+
55
+ # Add an event at the given time.
56
+ def schedule(time, callback)
57
+ handle = Handle.new(time.to_f, callback)
58
+
59
+ index = bisect_left(@sequence, handle)
60
+
61
+ # Maintain sorted order, O(logN) insertion time.
62
+ @sequence.insert(index, handle)
63
+
64
+ handle
65
+ end
66
+
67
+ # Returns the first non-cancelled handle.
68
+ def first
69
+ while (handle = @sequence.last)
70
+ return handle unless handle.cancelled?
71
+ @sequence.pop
72
+ end
73
+ end
74
+
75
+ # Returns the number of pending (possibly cancelled) events.
76
+ def size
77
+ @sequence.size
78
+ end
79
+
80
+ # Fire all handles for which Handle#time is less than the given time.
81
+ def fire(time)
82
+ pop(time).reverse_each do |handle|
83
+ handle.fire(time)
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ # Efficiently take k handles for which Handle#time is less than the given
90
+ # time.
91
+ def pop(time)
92
+ index = bisect_left(@sequence, time)
93
+
94
+ @sequence.pop(@sequence.size - index)
95
+ end
96
+
97
+ # Return the left-most index where to insert item e, in a list a, assuming
98
+ # a is sorted in descending order.
99
+ def bisect_left(a, e, l = 0, u = a.length)
100
+ while l < u
101
+ m = l + (u - l).div(2)
102
+
103
+ if a[m] > e
104
+ l = m + 1
105
+ else
106
+ u = m
107
+ end
108
+ end
109
+
110
+ l
111
+ end
112
+ end
111
113
  end
@@ -1,127 +1,132 @@
1
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
+ #
2
7
 
3
8
  require "set"
4
9
  require "forwardable"
5
- require "hitimes"
6
10
 
7
- require "timers/timer"
8
- require "timers/events"
11
+ require_relative "interval"
12
+ require_relative "timer"
13
+ require_relative "events"
9
14
 
10
15
  module Timers
11
- # A collection of timers which may fire at different times
12
- class Group
13
- include Enumerable
14
-
15
- extend Forwardable
16
- def_delegators :@timers, :each, :empty?
17
-
18
- def initialize
19
- @events = Events.new
20
-
21
- @timers = Set.new
22
- @paused_timers = Set.new
23
-
24
- @interval = Hitimes::Interval.new
25
- @interval.start
26
- end
27
-
28
- # Scheduled events:
29
- attr_reader :events
30
-
31
- # Active timers:
32
- attr_reader :timers
33
-
34
- # Paused timers:
35
- attr_reader :paused_timers
36
-
37
- # Call the given block after the given interval. The first argument will be
38
- # the time at which the group was asked to fire timers for.
39
- def after(interval, &block)
40
- Timer.new(self, interval, false, &block)
41
- end
42
-
43
- # Call the given block immediately, and then after the given interval. The first
44
- # argument will be the time at which the group was asked to fire timers for.
45
- def now_and_after(interval, &block)
46
- yield
47
- after(interval, &block)
48
- end
49
-
50
- # Call the given block periodically at the given interval. The first
51
- # argument will be the time at which the group was asked to fire timers for.
52
- def every(interval, recur = true, &block)
53
- Timer.new(self, interval, recur, &block)
54
- end
55
-
56
- # Call the given block immediately, and then periodically at the given interval. The first
57
- # argument will be the time at which the group was asked to fire timers for.
58
- def now_and_every(interval, recur = true, &block)
59
- yield
60
- every(interval, recur, &block)
61
- end
62
-
63
- # Wait for the next timer and fire it. Can take a block, which should behave
64
- # like sleep(n), except that n may be nil (sleep forever) or a negative
65
- # number (fire immediately after return).
66
- def wait
67
- if block_given?
68
- yield wait_interval
69
-
70
- while (interval = wait_interval) && interval > 0
71
- yield interval
72
- end
73
- else
74
- while (interval = wait_interval) && interval > 0
75
- # We cannot assume that sleep will wait for the specified time, it might be +/- a bit.
76
- sleep interval
77
- end
78
- end
79
-
80
- fire
81
- end
82
-
83
- # Interval to wait until when the next timer will fire.
84
- # - nil: no timers
85
- # - -ve: timers expired already
86
- # - 0: timers ready to fire
87
- # - +ve: timers waiting to fire
88
- def wait_interval(offset = current_offset)
89
- handle = @events.first
90
- handle.time - Float(offset) if handle
91
- end
92
-
93
- # Fire all timers that are ready.
94
- def fire(offset = current_offset)
95
- @events.fire(offset)
96
- end
97
-
98
- # Pause all timers.
99
- def pause
100
- @timers.dup.each(&:pause)
101
- end
102
-
103
- # Resume all timers.
104
- def resume
105
- @paused_timers.dup.each(&:resume)
106
- end
107
-
108
- alias continue resume
109
-
110
- # Delay all timers.
111
- def delay(seconds)
112
- @timers.each do |timer|
113
- timer.delay(seconds)
114
- end
115
- end
116
-
117
- # Cancel all timers.
118
- def cancel
119
- @timers.dup.each(&:cancel)
120
- end
121
-
122
- # The group's current time.
123
- def current_offset
124
- @interval.to_f
125
- end
126
- end
16
+ # A collection of timers which may fire at different times
17
+ class Group
18
+ include Enumerable
19
+
20
+ extend Forwardable
21
+ def_delegators :@timers, :each, :empty?
22
+
23
+ def initialize
24
+ @events = Events.new
25
+
26
+ @timers = Set.new
27
+ @paused_timers = Set.new
28
+
29
+ @interval = Interval.new
30
+ @interval.start
31
+ end
32
+
33
+ # Scheduled events:
34
+ attr_reader :events
35
+
36
+ # Active timers:
37
+ attr_reader :timers
38
+
39
+ # Paused timers:
40
+ attr_reader :paused_timers
41
+
42
+ # Call the given block after the given interval. The first argument will be
43
+ # the time at which the group was asked to fire timers for.
44
+ def after(interval, &block)
45
+ Timer.new(self, interval, false, &block)
46
+ end
47
+
48
+ # Call the given block immediately, and then after the given interval. The first
49
+ # argument will be the time at which the group was asked to fire timers for.
50
+ def now_and_after(interval, &block)
51
+ yield
52
+ after(interval, &block)
53
+ end
54
+
55
+ # Call the given block periodically at the given interval. The first
56
+ # argument will be the time at which the group was asked to fire timers for.
57
+ def every(interval, recur = true, &block)
58
+ Timer.new(self, interval, recur, &block)
59
+ end
60
+
61
+ # Call the given block immediately, and then periodically at the given interval. The first
62
+ # argument will be the time at which the group was asked to fire timers for.
63
+ def now_and_every(interval, recur = true, &block)
64
+ yield
65
+ every(interval, recur, &block)
66
+ end
67
+
68
+ # Wait for the next timer and fire it. Can take a block, which should behave
69
+ # like sleep(n), except that n may be nil (sleep forever) or a negative
70
+ # number (fire immediately after return).
71
+ def wait
72
+ if block_given?
73
+ yield wait_interval
74
+
75
+ while (interval = wait_interval) && interval > 0
76
+ yield interval
77
+ end
78
+ else
79
+ while (interval = wait_interval) && interval > 0
80
+ # We cannot assume that sleep will wait for the specified time, it might be +/- a bit.
81
+ sleep interval
82
+ end
83
+ end
84
+
85
+ fire
86
+ end
87
+
88
+ # Interval to wait until when the next timer will fire.
89
+ # - nil: no timers
90
+ # - -ve: timers expired already
91
+ # - 0: timers ready to fire
92
+ # - +ve: timers waiting to fire
93
+ def wait_interval(offset = current_offset)
94
+ handle = @events.first
95
+ handle.time - Float(offset) if handle
96
+ end
97
+
98
+ # Fire all timers that are ready.
99
+ def fire(offset = current_offset)
100
+ @events.fire(offset)
101
+ end
102
+
103
+ # Pause all timers.
104
+ def pause
105
+ @timers.dup.each(&:pause)
106
+ end
107
+
108
+ # Resume all timers.
109
+ def resume
110
+ @paused_timers.dup.each(&:resume)
111
+ end
112
+
113
+ alias continue resume
114
+
115
+ # Delay all timers.
116
+ def delay(seconds)
117
+ @timers.each do |timer|
118
+ timer.delay(seconds)
119
+ end
120
+ end
121
+
122
+ # Cancel all timers.
123
+ def cancel
124
+ @timers.dup.each(&:cancel)
125
+ end
126
+
127
+ # The group's current time.
128
+ def current_offset
129
+ @interval.to_f
130
+ end
131
+ end
127
132
  end