timers 4.3.0 → 4.3.5
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
- checksums.yaml.gz.sig +0 -0
- data/lib/timers/events.rb +37 -54
- data/lib/timers/group.rb +27 -26
- data/lib/timers/interval.rb +3 -5
- data/lib/timers/priority_heap.rb +146 -0
- data/lib/timers/timer.rb +48 -44
- data/lib/timers/version.rb +6 -6
- data/lib/timers/wait.rb +14 -13
- data/lib/timers.rb +18 -8
- data/license.md +48 -0
- data/readme.md +110 -0
- data.tar.gz.sig +0 -0
- metadata +109 -47
- metadata.gz.sig +0 -0
- data/.editorconfig +0 -6
- data/.gitignore +0 -17
- data/.rspec +0 -3
- data/.travis.yml +0 -20
- data/Gemfile +0 -15
- data/README.md +0 -149
- data/Rakefile +0 -6
- data/spec/spec_helper.rb +0 -40
- data/spec/timers/cancel_spec.rb +0 -50
- data/spec/timers/events_spec.rb +0 -61
- data/spec/timers/every_spec.rb +0 -38
- data/spec/timers/group_spec.rb +0 -260
- data/spec/timers/performance_spec.rb +0 -124
- data/spec/timers/strict_spec.rb +0 -39
- data/spec/timers/wait_spec.rb +0 -35
- data/timers.gemspec +0 -33
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e7c61c9db77955d85c69ca83499add3629c71628af3a825d78978b2383182b4a
|
|
4
|
+
data.tar.gz: 27f570753d83d4b4a98ee6ede089908d571347df8ba411edb56fe4ae965e703c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a7bac196cc0e3e1a784f7ba961c4a09539c875f80ac366da0b0d091d9f6ad1a505fb0a86a0c9d61d44a3495342029d003749b3ac072904b37f667d8e6e90b356
|
|
7
|
+
data.tar.gz: 4fa05113f72aef3abe63804a097e7fd9322c5b84a2a9ad14d590906e3ca59754857378a085388c52f9eb7ef1beb934b6b75789c3c087eee0b900f3446ace7207
|
checksums.yaml.gz.sig
ADDED
|
Binary file
|
data/lib/timers/events.rb
CHANGED
|
@@ -1,128 +1,111 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# Copyright,
|
|
6
|
-
#
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2014-2022, by Samuel Williams.
|
|
5
|
+
# Copyright, 2014-2016, by Tony Arcieri.
|
|
6
|
+
# Copyright, 2014, by Lavir the Whiolet.
|
|
7
|
+
# Copyright, 2015, by Utenmiki.
|
|
8
|
+
# Copyright, 2015, by Donovan Keme.
|
|
9
|
+
# Copyright, 2021, by Wander Hillen.
|
|
7
10
|
|
|
8
11
|
require_relative "timer"
|
|
12
|
+
require_relative "priority_heap"
|
|
9
13
|
|
|
10
14
|
module Timers
|
|
11
|
-
# Maintains
|
|
15
|
+
# Maintains a PriorityHeap of events ordered on time, which can be cancelled.
|
|
12
16
|
class Events
|
|
13
17
|
# Represents a cancellable handle for a specific timer event.
|
|
14
18
|
class Handle
|
|
19
|
+
include Comparable
|
|
20
|
+
|
|
15
21
|
def initialize(time, callback)
|
|
16
22
|
@time = time
|
|
17
23
|
@callback = callback
|
|
18
24
|
end
|
|
19
|
-
|
|
25
|
+
|
|
20
26
|
# The absolute time that the handle should be fired at.
|
|
21
27
|
attr_reader :time
|
|
22
|
-
|
|
28
|
+
|
|
23
29
|
# Cancel this timer, O(1).
|
|
24
30
|
def cancel!
|
|
25
31
|
# The simplest way to keep track of cancelled status is to nullify the
|
|
26
32
|
# callback. This should also be optimal for garbage collection.
|
|
27
33
|
@callback = nil
|
|
28
34
|
end
|
|
29
|
-
|
|
35
|
+
|
|
30
36
|
# Has this timer been cancelled? Cancelled timer's don't fire.
|
|
31
37
|
def cancelled?
|
|
32
38
|
@callback.nil?
|
|
33
39
|
end
|
|
34
|
-
|
|
35
|
-
def
|
|
36
|
-
@time
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def >= other
|
|
40
|
-
@time >= other.to_f
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def to_f
|
|
44
|
-
@time
|
|
40
|
+
|
|
41
|
+
def <=> other
|
|
42
|
+
@time <=> other.time
|
|
45
43
|
end
|
|
46
|
-
|
|
44
|
+
|
|
47
45
|
# Fire the callback if not cancelled with the given time parameter.
|
|
48
46
|
def fire(time)
|
|
49
47
|
@callback.call(time) if @callback
|
|
50
48
|
end
|
|
51
49
|
end
|
|
52
|
-
|
|
50
|
+
|
|
53
51
|
def initialize
|
|
54
52
|
# A sequence of handles, maintained in sorted order, future to present.
|
|
55
53
|
# @sequence.last is the next event to be fired.
|
|
56
|
-
@sequence =
|
|
54
|
+
@sequence = PriorityHeap.new
|
|
57
55
|
@queue = []
|
|
58
56
|
end
|
|
59
|
-
|
|
57
|
+
|
|
60
58
|
# Add an event at the given time.
|
|
61
59
|
def schedule(time, callback)
|
|
60
|
+
flush!
|
|
61
|
+
|
|
62
62
|
handle = Handle.new(time.to_f, callback)
|
|
63
63
|
|
|
64
64
|
@queue << handle
|
|
65
65
|
|
|
66
66
|
return handle
|
|
67
67
|
end
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
# Returns the first non-cancelled handle.
|
|
70
70
|
def first
|
|
71
71
|
merge!
|
|
72
72
|
|
|
73
|
-
while (handle = @sequence.
|
|
73
|
+
while (handle = @sequence.peek)
|
|
74
74
|
return handle unless handle.cancelled?
|
|
75
75
|
@sequence.pop
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
# Returns the number of pending (possibly cancelled) events.
|
|
80
80
|
def size
|
|
81
81
|
@sequence.size + @queue.size
|
|
82
82
|
end
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
# Fire all handles for which Handle#time is less than the given time.
|
|
85
85
|
def fire(time)
|
|
86
86
|
merge!
|
|
87
87
|
|
|
88
|
-
while handle = @sequence.
|
|
88
|
+
while handle = @sequence.peek and handle.time <= time
|
|
89
89
|
@sequence.pop
|
|
90
90
|
handle.fire(time)
|
|
91
91
|
end
|
|
92
92
|
end
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
private
|
|
95
|
-
|
|
95
|
+
|
|
96
|
+
# Move all non-cancelled timers from the pending queue to the priority heap
|
|
96
97
|
def merge!
|
|
97
98
|
while handle = @queue.pop
|
|
98
99
|
next if handle.cancelled?
|
|
99
100
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if current_handle = @sequence[index] and current_handle.cancelled?
|
|
103
|
-
# puts "Replacing handle at index: #{index} due to cancellation in array containing #{@sequence.size} item(s)."
|
|
104
|
-
@sequence[index] = handle
|
|
105
|
-
else
|
|
106
|
-
# puts "Inserting handle at index: #{index} in array containing #{@sequence.size} item(s)."
|
|
107
|
-
@sequence.insert(index, handle)
|
|
108
|
-
end
|
|
101
|
+
@sequence.push(handle)
|
|
109
102
|
end
|
|
110
103
|
end
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
while l < u
|
|
116
|
-
m = l + (u - l).div(2)
|
|
117
|
-
|
|
118
|
-
if a[m] >= e
|
|
119
|
-
l = m + 1
|
|
120
|
-
else
|
|
121
|
-
u = m
|
|
122
|
-
end
|
|
104
|
+
|
|
105
|
+
def flush!
|
|
106
|
+
while @queue.last&.cancelled?
|
|
107
|
+
@queue.pop
|
|
123
108
|
end
|
|
124
|
-
|
|
125
|
-
l
|
|
126
109
|
end
|
|
127
110
|
end
|
|
128
111
|
end
|
data/lib/timers/group.rb
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# Copyright,
|
|
6
|
-
#
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2014-2022, by Samuel Williams.
|
|
5
|
+
# Copyright, 2014-2016, by Tony Arcieri.
|
|
6
|
+
# Copyright, 2015, by Donovan Keme.
|
|
7
|
+
# Copyright, 2015, by Tommy Ong Gia Phu.
|
|
7
8
|
|
|
8
9
|
require "set"
|
|
9
10
|
require "forwardable"
|
|
@@ -16,62 +17,62 @@ module Timers
|
|
|
16
17
|
# A collection of timers which may fire at different times
|
|
17
18
|
class Group
|
|
18
19
|
include Enumerable
|
|
19
|
-
|
|
20
|
+
|
|
20
21
|
extend Forwardable
|
|
21
22
|
def_delegators :@timers, :each, :empty?
|
|
22
|
-
|
|
23
|
+
|
|
23
24
|
def initialize
|
|
24
25
|
@events = Events.new
|
|
25
|
-
|
|
26
|
+
|
|
26
27
|
@timers = Set.new
|
|
27
28
|
@paused_timers = Set.new
|
|
28
|
-
|
|
29
|
+
|
|
29
30
|
@interval = Interval.new
|
|
30
31
|
@interval.start
|
|
31
32
|
end
|
|
32
|
-
|
|
33
|
+
|
|
33
34
|
# Scheduled events:
|
|
34
35
|
attr_reader :events
|
|
35
|
-
|
|
36
|
+
|
|
36
37
|
# Active timers:
|
|
37
38
|
attr_reader :timers
|
|
38
|
-
|
|
39
|
+
|
|
39
40
|
# Paused timers:
|
|
40
41
|
attr_reader :paused_timers
|
|
41
|
-
|
|
42
|
+
|
|
42
43
|
# Call the given block after the given interval. The first argument will be
|
|
43
44
|
# the time at which the group was asked to fire timers for.
|
|
44
45
|
def after(interval, &block)
|
|
45
46
|
Timer.new(self, interval, false, &block)
|
|
46
47
|
end
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
# Call the given block immediately, and then after the given interval. The first
|
|
49
50
|
# argument will be the time at which the group was asked to fire timers for.
|
|
50
51
|
def now_and_after(interval, &block)
|
|
51
52
|
yield
|
|
52
53
|
after(interval, &block)
|
|
53
54
|
end
|
|
54
|
-
|
|
55
|
+
|
|
55
56
|
# Call the given block periodically at the given interval. The first
|
|
56
57
|
# argument will be the time at which the group was asked to fire timers for.
|
|
57
58
|
def every(interval, recur = true, &block)
|
|
58
59
|
Timer.new(self, interval, recur, &block)
|
|
59
60
|
end
|
|
60
|
-
|
|
61
|
+
|
|
61
62
|
# Call the given block immediately, and then periodically at the given interval. The first
|
|
62
63
|
# argument will be the time at which the group was asked to fire timers for.
|
|
63
64
|
def now_and_every(interval, recur = true, &block)
|
|
64
65
|
yield
|
|
65
66
|
every(interval, recur, &block)
|
|
66
67
|
end
|
|
67
|
-
|
|
68
|
+
|
|
68
69
|
# Wait for the next timer and fire it. Can take a block, which should behave
|
|
69
70
|
# like sleep(n), except that n may be nil (sleep forever) or a negative
|
|
70
71
|
# number (fire immediately after return).
|
|
71
72
|
def wait
|
|
72
73
|
if block_given?
|
|
73
74
|
yield wait_interval
|
|
74
|
-
|
|
75
|
+
|
|
75
76
|
while (interval = wait_interval) && interval > 0
|
|
76
77
|
yield interval
|
|
77
78
|
end
|
|
@@ -84,7 +85,7 @@ module Timers
|
|
|
84
85
|
|
|
85
86
|
fire
|
|
86
87
|
end
|
|
87
|
-
|
|
88
|
+
|
|
88
89
|
# Interval to wait until when the next timer will fire.
|
|
89
90
|
# - nil: no timers
|
|
90
91
|
# - -ve: timers expired already
|
|
@@ -94,36 +95,36 @@ module Timers
|
|
|
94
95
|
handle = @events.first
|
|
95
96
|
handle.time - Float(offset) if handle
|
|
96
97
|
end
|
|
97
|
-
|
|
98
|
+
|
|
98
99
|
# Fire all timers that are ready.
|
|
99
100
|
def fire(offset = current_offset)
|
|
100
101
|
@events.fire(offset)
|
|
101
102
|
end
|
|
102
|
-
|
|
103
|
+
|
|
103
104
|
# Pause all timers.
|
|
104
105
|
def pause
|
|
105
106
|
@timers.dup.each(&:pause)
|
|
106
107
|
end
|
|
107
|
-
|
|
108
|
+
|
|
108
109
|
# Resume all timers.
|
|
109
110
|
def resume
|
|
110
111
|
@paused_timers.dup.each(&:resume)
|
|
111
112
|
end
|
|
112
|
-
|
|
113
|
+
|
|
113
114
|
alias continue resume
|
|
114
|
-
|
|
115
|
+
|
|
115
116
|
# Delay all timers.
|
|
116
117
|
def delay(seconds)
|
|
117
118
|
@timers.each do |timer|
|
|
118
119
|
timer.delay(seconds)
|
|
119
120
|
end
|
|
120
121
|
end
|
|
121
|
-
|
|
122
|
+
|
|
122
123
|
# Cancel all timers.
|
|
123
124
|
def cancel
|
|
124
125
|
@timers.dup.each(&:cancel)
|
|
125
126
|
end
|
|
126
|
-
|
|
127
|
+
|
|
127
128
|
# The group's current time.
|
|
128
129
|
def current_offset
|
|
129
130
|
@interval.to_f
|
data/lib/timers/interval.rb
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# Copyright, 2018, by Samuel Williams. All rights reserved.
|
|
6
|
-
#
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2018-2022, by Samuel Williams.
|
|
7
5
|
|
|
8
6
|
module Timers
|
|
9
7
|
# A collection of timers which may fire at different times
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2021, by Wander Hillen.
|
|
5
|
+
# Copyright, 2021-2022, by Samuel Williams.
|
|
6
|
+
|
|
7
|
+
module Timers
|
|
8
|
+
# A priority queue implementation using a standard binary minheap. It uses straight comparison
|
|
9
|
+
# of its contents to determine priority. This works because a Handle from Timers::Events implements
|
|
10
|
+
# the '<' operation by comparing the expiry time.
|
|
11
|
+
# See <https://en.wikipedia.org/wiki/Binary_heap> for explanations of the main methods.
|
|
12
|
+
class PriorityHeap
|
|
13
|
+
def initialize
|
|
14
|
+
# The heap is represented with an array containing a binary tree. See
|
|
15
|
+
# https://en.wikipedia.org/wiki/Binary_heap#Heap_implementation for how this array
|
|
16
|
+
# is built up.
|
|
17
|
+
@contents = []
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Returns the earliest timer or nil if the heap is empty.
|
|
21
|
+
def peek
|
|
22
|
+
@contents[0]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Returns the number of elements in the heap
|
|
26
|
+
def size
|
|
27
|
+
@contents.size
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Returns the earliest timer if the heap is non-empty and removes it from the heap.
|
|
31
|
+
# Returns nil if the heap is empty. (and doesn't change the heap in that case)
|
|
32
|
+
def pop
|
|
33
|
+
# If the heap is empty:
|
|
34
|
+
if @contents.empty?
|
|
35
|
+
return nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# If we have only one item, no swapping is required:
|
|
39
|
+
if @contents.size == 1
|
|
40
|
+
return @contents.pop
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Take the root of the tree:
|
|
44
|
+
value = @contents[0]
|
|
45
|
+
|
|
46
|
+
# Remove the last item in the tree:
|
|
47
|
+
last = @contents.pop
|
|
48
|
+
|
|
49
|
+
# Overwrite the root of the tree with the item:
|
|
50
|
+
@contents[0] = last
|
|
51
|
+
|
|
52
|
+
# Bubble it down into place:
|
|
53
|
+
bubble_down(0)
|
|
54
|
+
|
|
55
|
+
# validate!
|
|
56
|
+
|
|
57
|
+
return value
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Inserts a new timer into the heap, then rearranges elements until the heap invariant is true again.
|
|
61
|
+
def push(element)
|
|
62
|
+
# Insert the item at the end of the heap:
|
|
63
|
+
@contents.push(element)
|
|
64
|
+
|
|
65
|
+
# Bubble it up into position:
|
|
66
|
+
bubble_up(@contents.size - 1)
|
|
67
|
+
|
|
68
|
+
# validate!
|
|
69
|
+
|
|
70
|
+
return self
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Empties out the heap, discarding all elements
|
|
74
|
+
def clear!
|
|
75
|
+
@contents = []
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Validate the heap invariant. Every element except the root must not be smaller than
|
|
79
|
+
# its parent element. Note that it MAY be equal.
|
|
80
|
+
def valid?
|
|
81
|
+
# notice we skip index 0 on purpose, because it has no parent
|
|
82
|
+
(1..(@contents.size - 1)).all? { |e| @contents[e] >= @contents[(e - 1) / 2] }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def swap(i, j)
|
|
88
|
+
@contents[i], @contents[j] = @contents[j], @contents[i]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def bubble_up(index)
|
|
92
|
+
parent_index = (index - 1) / 2 # watch out, integer division!
|
|
93
|
+
|
|
94
|
+
while index > 0 && @contents[index] < @contents[parent_index]
|
|
95
|
+
# if the node has a smaller value than its parent, swap these nodes
|
|
96
|
+
# to uphold the minheap invariant and update the index of the 'current'
|
|
97
|
+
# node. If the node is already at index 0, we can also stop because that
|
|
98
|
+
# is the root of the heap.
|
|
99
|
+
# swap(index, parent_index)
|
|
100
|
+
@contents[index], @contents[parent_index] = @contents[parent_index], @contents[index]
|
|
101
|
+
|
|
102
|
+
index = parent_index
|
|
103
|
+
parent_index = (index - 1) / 2 # watch out, integer division!
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def bubble_down(index)
|
|
108
|
+
swap_value = 0
|
|
109
|
+
swap_index = nil
|
|
110
|
+
|
|
111
|
+
while true
|
|
112
|
+
left_index = (2 * index) + 1
|
|
113
|
+
left_value = @contents[left_index]
|
|
114
|
+
|
|
115
|
+
if left_value.nil?
|
|
116
|
+
# This node has no children so it can't bubble down any further.
|
|
117
|
+
# We're done here!
|
|
118
|
+
return
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Determine which of the child nodes has the smallest value:
|
|
122
|
+
right_index = left_index + 1
|
|
123
|
+
right_value = @contents[right_index]
|
|
124
|
+
|
|
125
|
+
if right_value.nil? or right_value > left_value
|
|
126
|
+
swap_value = left_value
|
|
127
|
+
swap_index = left_index
|
|
128
|
+
else
|
|
129
|
+
swap_value = right_value
|
|
130
|
+
swap_index = right_index
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
if @contents[index] < swap_value
|
|
134
|
+
# No need to swap, the minheap invariant is already satisfied:
|
|
135
|
+
return
|
|
136
|
+
else
|
|
137
|
+
# At least one of the child node has a smaller value than the current node, swap current node with that child and update current node for if it might need to bubble down even further:
|
|
138
|
+
# swap(index, swap_index)
|
|
139
|
+
@contents[index], @contents[swap_index] = @contents[swap_index], @contents[index]
|
|
140
|
+
|
|
141
|
+
index = swap_index
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
data/lib/timers/timer.rb
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# Copyright,
|
|
6
|
-
#
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2014-2022, by Samuel Williams.
|
|
5
|
+
# Copyright, 2014-2017, by Tony Arcieri.
|
|
6
|
+
# Copyright, 2014, by Utenmiki.
|
|
7
|
+
# Copyright, 2014, by Lin Jen-Shin.
|
|
8
|
+
# Copyright, 2017, by Vít Ondruch.
|
|
7
9
|
|
|
8
10
|
module Timers
|
|
9
11
|
# An individual timer set to fire a given proc at a given time. A timer is
|
|
@@ -14,66 +16,66 @@ module Timers
|
|
|
14
16
|
class Timer
|
|
15
17
|
include Comparable
|
|
16
18
|
attr_reader :interval, :offset, :recurring
|
|
17
|
-
|
|
19
|
+
|
|
18
20
|
def initialize(group, interval, recurring = false, offset = nil, &block)
|
|
19
21
|
@group = group
|
|
20
|
-
|
|
22
|
+
|
|
21
23
|
@interval = interval
|
|
22
24
|
@recurring = recurring
|
|
23
25
|
@block = block
|
|
24
26
|
@offset = offset
|
|
25
|
-
|
|
27
|
+
|
|
26
28
|
@handle = nil
|
|
27
|
-
|
|
29
|
+
|
|
28
30
|
# If a start offset was supplied, use that, otherwise use the current timers offset.
|
|
29
31
|
reset(@offset || @group.current_offset)
|
|
30
32
|
end
|
|
31
|
-
|
|
33
|
+
|
|
32
34
|
def paused?
|
|
33
35
|
@group.paused_timers.include? self
|
|
34
36
|
end
|
|
35
|
-
|
|
37
|
+
|
|
36
38
|
def pause
|
|
37
39
|
return if paused?
|
|
38
|
-
|
|
40
|
+
|
|
39
41
|
@group.timers.delete self
|
|
40
42
|
@group.paused_timers.add self
|
|
41
|
-
|
|
43
|
+
|
|
42
44
|
@handle.cancel! if @handle
|
|
43
45
|
@handle = nil
|
|
44
46
|
end
|
|
45
|
-
|
|
47
|
+
|
|
46
48
|
def resume
|
|
47
49
|
return unless paused?
|
|
48
|
-
|
|
50
|
+
|
|
49
51
|
@group.paused_timers.delete self
|
|
50
|
-
|
|
52
|
+
|
|
51
53
|
# This will add us back to the group:
|
|
52
54
|
reset
|
|
53
55
|
end
|
|
54
|
-
|
|
56
|
+
|
|
55
57
|
alias continue resume
|
|
56
|
-
|
|
58
|
+
|
|
57
59
|
# Extend this timer
|
|
58
60
|
def delay(seconds)
|
|
59
61
|
@handle.cancel! if @handle
|
|
60
|
-
|
|
62
|
+
|
|
61
63
|
@offset += seconds
|
|
62
|
-
|
|
64
|
+
|
|
63
65
|
@handle = @group.events.schedule(@offset, self)
|
|
64
66
|
end
|
|
65
|
-
|
|
67
|
+
|
|
66
68
|
# Cancel this timer. Do not call while paused.
|
|
67
69
|
def cancel
|
|
68
70
|
return unless @handle
|
|
69
|
-
|
|
71
|
+
|
|
70
72
|
@handle.cancel! if @handle
|
|
71
73
|
@handle = nil
|
|
72
|
-
|
|
74
|
+
|
|
73
75
|
# This timer is no longer valid:
|
|
74
76
|
@group.timers.delete self if @group
|
|
75
77
|
end
|
|
76
|
-
|
|
78
|
+
|
|
77
79
|
# Reset this timer. Do not call while paused.
|
|
78
80
|
# @param offset [Numeric] the duration to add to the timer.
|
|
79
81
|
def reset(offset = @group.current_offset)
|
|
@@ -84,12 +86,12 @@ module Timers
|
|
|
84
86
|
else
|
|
85
87
|
@group.timers << self
|
|
86
88
|
end
|
|
87
|
-
|
|
89
|
+
|
|
88
90
|
@offset = Float(offset) + @interval
|
|
89
|
-
|
|
91
|
+
|
|
90
92
|
@handle = @group.events.schedule(@offset, self)
|
|
91
93
|
end
|
|
92
|
-
|
|
94
|
+
|
|
93
95
|
# Fire the block.
|
|
94
96
|
def fire(offset = @group.current_offset)
|
|
95
97
|
if recurring == :strict
|
|
@@ -100,36 +102,38 @@ module Timers
|
|
|
100
102
|
else
|
|
101
103
|
@offset = offset
|
|
102
104
|
end
|
|
103
|
-
|
|
105
|
+
|
|
104
106
|
@block.call(offset, self)
|
|
105
|
-
|
|
107
|
+
|
|
106
108
|
cancel unless recurring
|
|
107
109
|
end
|
|
108
|
-
|
|
110
|
+
|
|
109
111
|
alias call fire
|
|
110
|
-
|
|
112
|
+
|
|
111
113
|
# Number of seconds until next fire / since last fire
|
|
112
114
|
def fires_in
|
|
113
115
|
@offset - @group.current_offset if @offset
|
|
114
116
|
end
|
|
115
|
-
|
|
117
|
+
|
|
116
118
|
# Inspect a timer
|
|
117
119
|
def inspect
|
|
118
|
-
|
|
119
|
-
|
|
120
|
+
buffer = "#{to_s[0..-2]} ".dup
|
|
121
|
+
|
|
120
122
|
if @offset
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
123
|
+
if fires_in >= 0
|
|
124
|
+
buffer << "fires in #{fires_in} seconds"
|
|
125
|
+
else
|
|
126
|
+
buffer << "fired #{fires_in.abs} seconds ago"
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
buffer << ", recurs every #{interval}" if recurring
|
|
128
130
|
else
|
|
129
|
-
|
|
131
|
+
buffer << "dead"
|
|
130
132
|
end
|
|
131
|
-
|
|
132
|
-
|
|
133
|
+
|
|
134
|
+
buffer << ">"
|
|
135
|
+
|
|
136
|
+
return buffer
|
|
133
137
|
end
|
|
134
138
|
end
|
|
135
139
|
end
|
data/lib/timers/version.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# Copyright,
|
|
6
|
-
#
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2012-2016, by Tony Arcieri.
|
|
5
|
+
# Copyright, 2014-2022, by Samuel Williams.
|
|
6
|
+
# Copyright, 2015, by Donovan Keme.
|
|
7
7
|
|
|
8
8
|
module Timers
|
|
9
|
-
VERSION = "4.3.
|
|
9
|
+
VERSION = "4.3.5"
|
|
10
10
|
end
|