timers 4.1.2 → 4.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module Timers
24
+ # A collection of timers which may fire at different times
25
+ class Interval
26
+ # Get the current elapsed monotonic time.
27
+ def initialize
28
+ @total = 0.0
29
+ @current = nil
30
+ end
31
+
32
+ def start
33
+ return if @current
34
+
35
+ @current = now
36
+ end
37
+
38
+ def stop
39
+ return unless @current
40
+
41
+ @total += duration
42
+
43
+ @current = nil
44
+ end
45
+
46
+ def to_f
47
+ @total + duration
48
+ end
49
+
50
+ protected def duration
51
+ now - @current
52
+ end
53
+
54
+ protected def now
55
+ ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
56
+ end
57
+ end
58
+ end
@@ -1,129 +1,150 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Timers
4
- # An individual timer set to fire a given proc at a given time. A timer is
5
- # always connected to a Timer::Group but it would ONLY be in @group.timers
6
- # if it also has a @handle specified. Otherwise it is either PAUSED or has
7
- # been FIRED and is not recurring. You can manually enter this state by
8
- # calling #cancel and resume normal operation by calling #reset.
9
- class Timer
10
- include Comparable
11
- attr_reader :interval, :offset, :recurring
3
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
12
22
 
13
- def initialize(group, interval, recurring = false, offset = nil, &block)
14
- @group = group
23
+ module Timers
24
+ # An individual timer set to fire a given proc at a given time. A timer is
25
+ # always connected to a Timer::Group but it would ONLY be in @group.timers
26
+ # if it also has a @handle specified. Otherwise it is either PAUSED or has
27
+ # been FIRED and is not recurring. You can manually enter this state by
28
+ # calling #cancel and resume normal operation by calling #reset.
29
+ class Timer
30
+ include Comparable
31
+ attr_reader :interval, :offset, :recurring
15
32
 
16
- @interval = interval
17
- @recurring = recurring
18
- @block = block
19
- @offset = offset
33
+ def initialize(group, interval, recurring = false, offset = nil, &block)
34
+ @group = group
20
35
 
21
- @handle = nil
36
+ @interval = interval
37
+ @recurring = recurring
38
+ @block = block
39
+ @offset = offset
40
+
41
+ @handle = nil
22
42
 
23
- # If a start offset was supplied, use that, otherwise use the current timers offset.
24
- reset(@offset || @group.current_offset)
25
- end
43
+ # If a start offset was supplied, use that, otherwise use the current timers offset.
44
+ reset(@offset || @group.current_offset)
45
+ end
26
46
 
27
- def paused?
28
- @group.paused_timers.include? self
29
- end
30
-
31
- def pause
32
- return if paused?
33
-
34
- @group.timers.delete self
35
- @group.paused_timers.add self
36
-
37
- @handle.cancel! if @handle
38
- @handle = nil
39
- end
40
-
41
- def resume
42
- return unless paused?
43
-
44
- @group.paused_timers.delete self
45
-
46
- # This will add us back to the group:
47
- reset
48
- end
49
-
50
- alias continue resume
51
-
52
- # Extend this timer
53
- def delay(seconds)
54
- @handle.cancel! if @handle
55
-
56
- @offset += seconds
57
-
58
- @handle = @group.events.schedule(@offset, self)
59
- end
60
-
61
- # Cancel this timer. Do not call while paused.
62
- def cancel
63
- return unless @handle
64
-
65
- @handle.cancel! if @handle
66
- @handle = nil
67
-
68
- # This timer is no longer valid:
69
- @group.timers.delete self if @group
70
- end
71
-
72
- # Reset this timer. Do not call while paused.
73
- def reset(offset = @group.current_offset)
74
- # This logic allows us to minimise the interaction with @group.timers.
75
- # A timer with a handle is always registered with the group.
76
- if @handle
77
- @handle.cancel!
78
- else
79
- @group.timers << self
80
- end
81
-
82
- @offset = Float(offset) + @interval
83
-
84
- @handle = @group.events.schedule(@offset, self)
85
- end
86
-
87
- # Fire the block.
88
- def fire(offset = @group.current_offset)
89
- if recurring == :strict
90
- # ... make the next interval strictly the last offset + the interval:
91
- reset(@offset)
92
- elsif recurring
93
- reset(offset)
94
- else
95
- @offset = offset
96
- end
97
-
98
- @block.call(offset)
99
-
100
- cancel unless recurring
101
- end
102
-
103
- alias call fire
104
-
105
- # Number of seconds until next fire / since last fire
106
- def fires_in
107
- @offset - @group.current_offset if @offset
108
- end
47
+ def paused?
48
+ @group.paused_timers.include? self
49
+ end
50
+
51
+ def pause
52
+ return if paused?
53
+
54
+ @group.timers.delete self
55
+ @group.paused_timers.add self
56
+
57
+ @handle.cancel! if @handle
58
+ @handle = nil
59
+ end
60
+
61
+ def resume
62
+ return unless paused?
63
+
64
+ @group.paused_timers.delete self
65
+
66
+ # This will add us back to the group:
67
+ reset
68
+ end
69
+
70
+ alias continue resume
71
+
72
+ # Extend this timer
73
+ def delay(seconds)
74
+ @handle.cancel! if @handle
75
+
76
+ @offset += seconds
77
+
78
+ @handle = @group.events.schedule(@offset, self)
79
+ end
80
+
81
+ # Cancel this timer. Do not call while paused.
82
+ def cancel
83
+ return unless @handle
84
+
85
+ @handle.cancel! if @handle
86
+ @handle = nil
87
+
88
+ # This timer is no longer valid:
89
+ @group.timers.delete self if @group
90
+ end
91
+
92
+ # Reset this timer. Do not call while paused.
93
+ # @param offset [Numeric] the duration to add to the timer.
94
+ def reset(offset = @group.current_offset)
95
+ # This logic allows us to minimise the interaction with @group.timers.
96
+ # A timer with a handle is always registered with the group.
97
+ if @handle
98
+ @handle.cancel!
99
+ else
100
+ @group.timers << self
101
+ end
102
+
103
+ @offset = Float(offset) + @interval
104
+
105
+ @handle = @group.events.schedule(@offset, self)
106
+ end
107
+
108
+ # Fire the block.
109
+ def fire(offset = @group.current_offset)
110
+ if recurring == :strict
111
+ # ... make the next interval strictly the last offset + the interval:
112
+ reset(@offset)
113
+ elsif recurring
114
+ reset(offset)
115
+ else
116
+ @offset = offset
117
+ end
118
+
119
+ @block.call(offset, self)
120
+
121
+ cancel unless recurring
122
+ end
123
+
124
+ alias call fire
125
+
126
+ # Number of seconds until next fire / since last fire
127
+ def fires_in
128
+ @offset - @group.current_offset if @offset
129
+ end
109
130
 
110
- # Inspect a timer
111
- def inspect
112
- str = "#<Timers::Timer:#{object_id.to_s(16)} ".dup
131
+ # Inspect a timer
132
+ def inspect
133
+ str = "#{to_s[0..-2]} ".dup
113
134
 
114
- if @offset
115
- str << if fires_in >= 0
116
- "fires in #{fires_in} seconds"
117
- else
118
- "fired #{fires_in.abs} seconds ago"
119
- end
135
+ if @offset
136
+ str << if fires_in >= 0
137
+ "fires in #{fires_in} seconds"
138
+ else
139
+ "fired #{fires_in.abs} seconds ago"
140
+ end
120
141
 
121
- str << ", recurs every #{interval}" if recurring
122
- else
123
- str << "dead"
124
- end
142
+ str << ", recurs every #{interval}" if recurring
143
+ else
144
+ str << "dead"
145
+ end
125
146
 
126
- str << ">"
127
- end
128
- end
147
+ str << ">"
148
+ end
149
+ end
129
150
  end
@@ -1,5 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
3
23
  module Timers
4
- VERSION = "4.1.2"
24
+ VERSION = "4.3.2"
5
25
  end
@@ -1,47 +1,67 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "hitimes"
3
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative "interval"
4
24
 
5
25
  module Timers
6
- # An exclusive, monotonic timeout class.
7
- class Wait
8
- def self.for(duration, &block)
9
- if duration
10
- timeout = new(duration)
11
-
12
- timeout.while_time_remaining(&block)
13
- else
14
- loop do
15
- yield(nil)
16
- end
17
- end
18
- end
19
-
20
- def initialize(duration)
21
- @duration = duration
22
- @remaining = true
23
- end
24
-
25
- attr_reader :duration
26
- attr_reader :remaining
27
-
28
- # Yields while time remains for work to be done:
29
- def while_time_remaining
30
- @interval = Hitimes::Interval.new
31
- @interval.start
32
-
33
- yield @remaining while time_remaining?
34
- ensure
35
- @interval.stop
36
- @interval = nil
37
- end
38
-
39
- private
40
-
41
- def time_remaining?
42
- @remaining = (@duration - @interval.duration)
43
-
44
- @remaining > 0
45
- end
46
- end
26
+ # An exclusive, monotonic timeout class.
27
+ class Wait
28
+ def self.for(duration, &block)
29
+ if duration
30
+ timeout = new(duration)
31
+
32
+ timeout.while_time_remaining(&block)
33
+ else
34
+ loop do
35
+ yield(nil)
36
+ end
37
+ end
38
+ end
39
+
40
+ def initialize(duration)
41
+ @duration = duration
42
+ @remaining = true
43
+ end
44
+
45
+ attr_reader :duration
46
+ attr_reader :remaining
47
+
48
+ # Yields while time remains for work to be done:
49
+ def while_time_remaining
50
+ @interval = Interval.new
51
+ @interval.start
52
+
53
+ yield @remaining while time_remaining?
54
+ ensure
55
+ @interval.stop
56
+ @interval = nil
57
+ end
58
+
59
+ private
60
+
61
+ def time_remaining?
62
+ @remaining = (@duration - @interval.to_f)
63
+
64
+ @remaining > 0
65
+ end
66
+ end
47
67
  end