io-event 1.7.4 → 1.7.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/ext/io/event/selector/epoll.c +1 -1
- data/lib/io/event/debug/selector.rb +41 -1
- data/lib/io/event/priority_heap.rb +13 -14
- data/lib/io/event/selector/nonblock.rb +4 -0
- data/lib/io/event/selector/select.rb +19 -3
- data/lib/io/event/selector.rb +10 -0
- data/lib/io/event/support.rb +12 -0
- data/lib/io/event/timers.rb +41 -3
- data/lib/io/event/version.rb +3 -1
- data/readme.md +11 -1
- data/releases.md +5 -0
- data.tar.gz.sig +0 -0
- metadata +3 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab271a1de3eb0f5d21b0b7c92cafcc226e5ca218e7b87ebaa80f93a54fd7b945
|
4
|
+
data.tar.gz: fa6227d0b4218b277903fb1c6f1889e51bcfb7e8d8f83086edc30a336a065eff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5afc83ef6364791d86b14bdf130d68fda3a7a1c720349dce6bb2140a2ee9f69015e542dbf5c724a0daa338e5f13c87f1dee566e8a36a1b0847ce5e86e1fa92b
|
7
|
+
data.tar.gz: 7d09237e5141123bf251fe686e25fca7d8391a7c25fe331e8882d7e43bf87ff9c5e89bc5c5f90d0731705b923eade10c4667344ad06d04a08544bb9a944baa28
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -519,7 +519,7 @@ VALUE IO_Event_Selector_EPoll_process_wait(VALUE self, VALUE fiber, VALUE _pid,
|
|
519
519
|
|
520
520
|
RB_OBJ_WRITTEN(self, Qundef, fiber);
|
521
521
|
|
522
|
-
int result = IO_Event_Selector_EPoll_Waiting_register(selector,
|
522
|
+
int result = IO_Event_Selector_EPoll_Waiting_register(selector, _pid, descriptor, &waiting);
|
523
523
|
|
524
524
|
if (result == -1) {
|
525
525
|
close(descriptor);
|
@@ -6,9 +6,16 @@
|
|
6
6
|
require_relative "../support"
|
7
7
|
|
8
8
|
module IO::Event
|
9
|
+
# @namespace
|
9
10
|
module Debug
|
10
11
|
# Enforces the selector interface and delegates operations to a wrapped selector instance.
|
12
|
+
#
|
13
|
+
# You can enable this in the default selector by setting the `IO_EVENT_DEBUG_SELECTOR` environment variable. In addition, you can log all selector operations to a file by setting the `IO_EVENT_DEBUG_SELECTOR_LOG` environment variable. This is useful for debugging and understanding the behavior of the event loop.
|
11
14
|
class Selector
|
15
|
+
# Wrap the given selector with debugging.
|
16
|
+
#
|
17
|
+
# @parameter selector [Selector] The selector to wrap.
|
18
|
+
# @parameter env [Hash] The environment to read configuration from.
|
12
19
|
def self.wrap(selector, env = ENV)
|
13
20
|
log = nil
|
14
21
|
|
@@ -19,6 +26,10 @@ module IO::Event
|
|
19
26
|
return self.new(selector, log: log)
|
20
27
|
end
|
21
28
|
|
29
|
+
# Initialize the debug selector with the given selector and optional log.
|
30
|
+
#
|
31
|
+
# @parameter selector [Selector] The selector to wrap.
|
32
|
+
# @parameter log [IO] The log to write debug messages to.
|
22
33
|
def initialize(selector, log: nil)
|
23
34
|
@selector = selector
|
24
35
|
|
@@ -33,14 +44,23 @@ module IO::Event
|
|
33
44
|
@log = log
|
34
45
|
end
|
35
46
|
|
47
|
+
# The idle duration of the underlying selector.
|
48
|
+
#
|
49
|
+
# @returns [Numeric] The idle duration.
|
36
50
|
def idle_duration
|
37
51
|
@selector.idle_duration
|
38
52
|
end
|
39
53
|
|
54
|
+
# The current time.
|
55
|
+
#
|
56
|
+
# @returns [Numeric] The current time.
|
40
57
|
def now
|
41
58
|
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
42
59
|
end
|
43
60
|
|
61
|
+
# Log the given message.
|
62
|
+
#
|
63
|
+
# @asynchronous Will block the calling fiber and the entire event loop.
|
44
64
|
def log(message)
|
45
65
|
return unless @log
|
46
66
|
|
@@ -49,10 +69,12 @@ module IO::Event
|
|
49
69
|
end
|
50
70
|
end
|
51
71
|
|
72
|
+
# Wakeup the the selector.
|
52
73
|
def wakeup
|
53
74
|
@selector.wakeup
|
54
75
|
end
|
55
76
|
|
77
|
+
# Close the selector.
|
56
78
|
def close
|
57
79
|
log("Closing selector")
|
58
80
|
|
@@ -64,60 +86,78 @@ module IO::Event
|
|
64
86
|
@selector = nil
|
65
87
|
end
|
66
88
|
|
67
|
-
# Transfer from the calling fiber to the
|
89
|
+
# Transfer from the calling fiber to the selector.
|
68
90
|
def transfer
|
69
91
|
log("Transfering to event loop")
|
70
92
|
@selector.transfer
|
71
93
|
end
|
72
94
|
|
95
|
+
# Resume the given fiber with the given arguments.
|
73
96
|
def resume(*arguments)
|
74
97
|
log("Resuming fiber with #{arguments.inspect}")
|
75
98
|
@selector.resume(*arguments)
|
76
99
|
end
|
77
100
|
|
101
|
+
# Yield to the selector.
|
78
102
|
def yield
|
79
103
|
log("Yielding to event loop")
|
80
104
|
@selector.yield
|
81
105
|
end
|
82
106
|
|
107
|
+
# Push the given fiber to the selector ready list, such that it will be resumed on the next call to {select}.
|
108
|
+
#
|
109
|
+
# @parameter fiber [Fiber] The fiber that is ready.
|
83
110
|
def push(fiber)
|
84
111
|
log("Pushing fiber #{fiber.inspect} to ready list")
|
85
112
|
@selector.push(fiber)
|
86
113
|
end
|
87
114
|
|
115
|
+
# Raise the given exception on the given fiber.
|
116
|
+
#
|
117
|
+
# @parameter fiber [Fiber] The fiber to raise the exception on.
|
118
|
+
# @parameter arguments [Array] The arguments to use when raising the exception.
|
88
119
|
def raise(fiber, *arguments)
|
89
120
|
log("Raising exception on fiber #{fiber.inspect} with #{arguments.inspect}")
|
90
121
|
@selector.raise(fiber, *arguments)
|
91
122
|
end
|
92
123
|
|
124
|
+
# Check if the selector is ready.
|
125
|
+
#
|
126
|
+
# @returns [Boolean] Whether the selector is ready.
|
93
127
|
def ready?
|
94
128
|
@selector.ready?
|
95
129
|
end
|
96
130
|
|
131
|
+
# Wait for the given process, forwarded to the underlying selector.
|
97
132
|
def process_wait(*arguments)
|
98
133
|
log("Waiting for process with #{arguments.inspect}")
|
99
134
|
@selector.process_wait(*arguments)
|
100
135
|
end
|
101
136
|
|
137
|
+
# Wait for the given IO, forwarded to the underlying selector.
|
102
138
|
def io_wait(fiber, io, events)
|
103
139
|
log("Waiting for IO #{io.inspect} for events #{events.inspect}")
|
104
140
|
@selector.io_wait(fiber, io, events)
|
105
141
|
end
|
106
142
|
|
143
|
+
# Read from the given IO, forwarded to the underlying selector.
|
107
144
|
def io_read(fiber, io, buffer, length, offset = 0)
|
108
145
|
log("Reading from IO #{io.inspect} with buffer #{buffer}; length #{length} offset #{offset}")
|
109
146
|
@selector.io_read(fiber, io, buffer, length, offset)
|
110
147
|
end
|
111
148
|
|
149
|
+
# Write to the given IO, forwarded to the underlying selector.
|
112
150
|
def io_write(fiber, io, buffer, length, offset = 0)
|
113
151
|
log("Writing to IO #{io.inspect} with buffer #{buffer}; length #{length} offset #{offset}")
|
114
152
|
@selector.io_write(fiber, io, buffer, length, offset)
|
115
153
|
end
|
116
154
|
|
155
|
+
# Forward the given method to the underlying selector.
|
117
156
|
def respond_to?(name, include_private = false)
|
118
157
|
@selector.respond_to?(name, include_private)
|
119
158
|
end
|
120
159
|
|
160
|
+
# Select for the given duration, forwarded to the underlying selector.
|
121
161
|
def select(duration = nil)
|
122
162
|
log("Selecting for #{duration.inspect}")
|
123
163
|
unless Fiber.current == @selector.loop
|
@@ -10,6 +10,7 @@ class IO
|
|
10
10
|
# of its contents to determine priority.
|
11
11
|
# See <https://en.wikipedia.org/wiki/Binary_heap> for explanations of the main methods.
|
12
12
|
class PriorityHeap
|
13
|
+
# Initializes the heap.
|
13
14
|
def initialize
|
14
15
|
# The heap is represented with an array containing a binary tree. See
|
15
16
|
# https://en.wikipedia.org/wiki/Binary_heap#Heap_implementation for how this array
|
@@ -17,18 +18,19 @@ class IO
|
|
17
18
|
@contents = []
|
18
19
|
end
|
19
20
|
|
20
|
-
#
|
21
|
+
# @returns [Object | Nil] the smallest element in the heap without removing it, or nil if the heap is empty.
|
21
22
|
def peek
|
22
23
|
@contents[0]
|
23
24
|
end
|
24
25
|
|
25
|
-
#
|
26
|
+
# @returns [Integer] the number of elements in the heap.
|
26
27
|
def size
|
27
28
|
@contents.size
|
28
29
|
end
|
29
30
|
|
30
|
-
#
|
31
|
-
#
|
31
|
+
# Removes and returns the smallest element in the heap, or nil if the heap is empty.
|
32
|
+
#
|
33
|
+
# @returns [Object | Nil] The smallest element in the heap, or nil if the heap is empty.
|
32
34
|
def pop
|
33
35
|
# If the heap is empty:
|
34
36
|
if @contents.empty?
|
@@ -57,7 +59,9 @@ class IO
|
|
57
59
|
return value
|
58
60
|
end
|
59
61
|
|
60
|
-
#
|
62
|
+
# Add a new element to the heap, then rearrange elements until the heap invariant is true again.
|
63
|
+
#
|
64
|
+
# @parameter element [Object] The element to add to the heap.
|
61
65
|
def push(element)
|
62
66
|
# Insert the item at the end of the heap:
|
63
67
|
@contents.push(element)
|
@@ -75,10 +79,9 @@ class IO
|
|
75
79
|
@contents = []
|
76
80
|
end
|
77
81
|
|
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.
|
82
|
+
# Validate the heap invariant. Every element except the root must not be smaller than its parent element. Note that it MAY be equal.
|
80
83
|
def valid?
|
81
|
-
#
|
84
|
+
# Notice we skip index 0 on purpose, because it has no parent
|
82
85
|
(1..(@contents.size - 1)).all? { |e| @contents[e] >= @contents[(e - 1) / 2] }
|
83
86
|
end
|
84
87
|
|
@@ -93,10 +96,7 @@ class IO
|
|
93
96
|
parent_index = (index - 1) / 2 # watch out, integer division!
|
94
97
|
|
95
98
|
while index > 0 && @contents[index] < @contents[parent_index]
|
96
|
-
#
|
97
|
-
# to uphold the minheap invariant and update the index of the 'current'
|
98
|
-
# node. If the node is already at index 0, we can also stop because that
|
99
|
-
# is the root of the heap.
|
99
|
+
# If the node has a smaller value than its parent, swap these nodes to uphold the minheap invariant and update the index of the 'current' node. If the node is already at index 0, we can also stop because that is the root of the heap.
|
100
100
|
# swap(index, parent_index)
|
101
101
|
@contents[index], @contents[parent_index] = @contents[parent_index], @contents[index]
|
102
102
|
|
@@ -114,8 +114,7 @@ class IO
|
|
114
114
|
left_value = @contents[left_index]
|
115
115
|
|
116
116
|
if left_value.nil?
|
117
|
-
# This node has no children so it can't bubble down any further.
|
118
|
-
# We're done here!
|
117
|
+
# This node has no children so it can't bubble down any further. We're done here!
|
119
118
|
return
|
120
119
|
end
|
121
120
|
|
@@ -7,6 +7,10 @@ require "io/nonblock"
|
|
7
7
|
|
8
8
|
module IO::Event
|
9
9
|
module Selector
|
10
|
+
# Execute the given block in non-blocking mode.
|
11
|
+
#
|
12
|
+
# @parameter io [IO] The IO object to operate on.
|
13
|
+
# @yields {...} The block to execute.
|
10
14
|
def self.nonblock(io, &block)
|
11
15
|
io.nonblock(&block)
|
12
16
|
rescue Errno::EBADF
|
@@ -9,7 +9,9 @@ require_relative "../support"
|
|
9
9
|
|
10
10
|
module IO::Event
|
11
11
|
module Selector
|
12
|
+
# A pure-Ruby implementation of the event selector.
|
12
13
|
class Select
|
14
|
+
# Initialize the selector with the given event loop fiber.
|
13
15
|
def initialize(loop)
|
14
16
|
@loop = loop
|
15
17
|
|
@@ -23,12 +25,13 @@ module IO::Event
|
|
23
25
|
@idle_duration = 0.0
|
24
26
|
end
|
25
27
|
|
28
|
+
# @attribute [Fiber] The event loop fiber.
|
26
29
|
attr :loop
|
27
30
|
|
28
|
-
# This is the amount of time the event loop was idle during the last select call.
|
31
|
+
# @attribute [Float] This is the amount of time the event loop was idle during the last select call.
|
29
32
|
attr :idle_duration
|
30
33
|
|
31
|
-
#
|
34
|
+
# Wake up the event loop if it is currently sleeping.
|
32
35
|
def wakeup
|
33
36
|
if @blocked
|
34
37
|
@interrupt.signal
|
@@ -39,6 +42,7 @@ module IO::Event
|
|
39
42
|
return false
|
40
43
|
end
|
41
44
|
|
45
|
+
# Close the selector and release any resources.
|
42
46
|
def close
|
43
47
|
@interrupt.close
|
44
48
|
|
@@ -100,6 +104,7 @@ module IO::Event
|
|
100
104
|
optional.nullify
|
101
105
|
end
|
102
106
|
|
107
|
+
# @returns [Boolean] Whether the ready list is not empty, i.e. there are fibers ready to be resumed.
|
103
108
|
def ready?
|
104
109
|
!@ready.empty?
|
105
110
|
end
|
@@ -144,6 +149,11 @@ module IO::Event
|
|
144
149
|
end
|
145
150
|
end
|
146
151
|
|
152
|
+
# Wait for the given IO to become readable or writable.
|
153
|
+
#
|
154
|
+
# @parameter fiber [Fiber] The fiber that is waiting.
|
155
|
+
# @parameter io [IO] The IO object to wait on.
|
156
|
+
# @parameter events [Integer] The events to wait for.
|
147
157
|
def io_wait(fiber, io, events)
|
148
158
|
waiter = @waiting[io] = Waiter.new(fiber, events, @waiting[io])
|
149
159
|
|
@@ -152,6 +162,11 @@ module IO::Event
|
|
152
162
|
waiter&.invalidate
|
153
163
|
end
|
154
164
|
|
165
|
+
# Wait for multiple IO objects to become readable or writable.
|
166
|
+
#
|
167
|
+
# @parameter readable [Array(IO)] The list of IO objects to wait for readability.
|
168
|
+
# @parameter writable [Array(IO)] The list of IO objects to wait for writability.
|
169
|
+
# @parameter priority [Array(IO)] The list of IO objects to wait for priority events.
|
155
170
|
def io_select(readable, writable, priority, timeout)
|
156
171
|
Thread.new do
|
157
172
|
IO.select(readable, writable, priority, timeout)
|
@@ -161,7 +176,8 @@ module IO::Event
|
|
161
176
|
EAGAIN = -Errno::EAGAIN::Errno
|
162
177
|
EWOULDBLOCK = -Errno::EWOULDBLOCK::Errno
|
163
178
|
|
164
|
-
|
179
|
+
# Whether the given error code indicates that the operation should be retried.
|
180
|
+
protected def again?(errno)
|
165
181
|
errno == EAGAIN or errno == EWOULDBLOCK
|
166
182
|
end
|
167
183
|
|
data/lib/io/event/selector.rb
CHANGED
@@ -8,7 +8,12 @@ require_relative "debug/selector"
|
|
8
8
|
require_relative "support"
|
9
9
|
|
10
10
|
module IO::Event
|
11
|
+
# @namespace
|
11
12
|
module Selector
|
13
|
+
# The default selector implementation, which is chosen based on the environment and available implementations.
|
14
|
+
#
|
15
|
+
# @parameter env [Hash] The environment to read configuration from.
|
16
|
+
# @returns [Class] The default selector implementation.
|
12
17
|
def self.default(env = ENV)
|
13
18
|
if name = env["IO_EVENT_SELECTOR"]&.to_sym
|
14
19
|
return const_get(name)
|
@@ -25,6 +30,11 @@ module IO::Event
|
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
33
|
+
# Create a new selector instance, according to the best available implementation.
|
34
|
+
#
|
35
|
+
# @parameter loop [Fiber] The event loop fiber.
|
36
|
+
# @parameter env [Hash] The environment to read configuration from.
|
37
|
+
# @returns [Selector] The new selector instance.
|
28
38
|
def self.new(loop, env = ENV)
|
29
39
|
selector = default(env).new(loop)
|
30
40
|
|
data/lib/io/event/support.rb
CHANGED
@@ -5,16 +5,26 @@
|
|
5
5
|
|
6
6
|
class IO
|
7
7
|
module Event
|
8
|
+
# Helper methods for detecting support for various features.
|
8
9
|
module Support
|
10
|
+
# Some features are only availble if the IO::Buffer class is available.
|
11
|
+
#
|
12
|
+
# @returns [Boolean] Whether the IO::Buffer class is available.
|
9
13
|
def self.buffer?
|
10
14
|
IO.const_defined?(:Buffer)
|
11
15
|
end
|
12
16
|
|
17
|
+
# The basic fiber scheduler was introduced along side the IO::Buffer class.
|
18
|
+
#
|
19
|
+
# @returns [Boolean] Whether the IO::Buffer class is available.
|
20
|
+
#
|
13
21
|
# To be removed on 31 Mar 2025.
|
14
22
|
def self.fiber_scheduler_v1?
|
15
23
|
IO.const_defined?(:Buffer)
|
16
24
|
end
|
17
25
|
|
26
|
+
# More advanced read/write methods and blocking controls were introduced in Ruby 3.2.
|
27
|
+
#
|
18
28
|
# To be removed on 31 Mar 2026.
|
19
29
|
def self.fiber_scheduler_v2?
|
20
30
|
# Some interface changes were back-ported incorrectly:
|
@@ -26,6 +36,8 @@ class IO
|
|
26
36
|
IO.const_defined?(:Buffer) and Fiber.respond_to?(:blocking) and IO::Buffer.instance_method(:read).arity == -1
|
27
37
|
end
|
28
38
|
|
39
|
+
# Updated inferfaces for read/write and IO::Buffer were introduced in Ruby 3.3, including pread/pwrite.
|
40
|
+
#
|
29
41
|
# To become the default 31 Mar 2026.
|
30
42
|
def self.fiber_scheduler_v3?
|
31
43
|
if fiber_scheduler_v2?
|
data/lib/io/event/timers.rb
CHANGED
@@ -7,42 +7,64 @@ require_relative "priority_heap"
|
|
7
7
|
|
8
8
|
class IO
|
9
9
|
module Event
|
10
|
+
# An efficient sorted set of timers.
|
10
11
|
class Timers
|
12
|
+
# A handle to a scheduled timer.
|
11
13
|
class Handle
|
14
|
+
# Initialize the handle with the given time and block.
|
15
|
+
#
|
16
|
+
# @parameter time [Float] The time at which the block should be called.
|
17
|
+
# @parameter block [Proc] The block to call.
|
12
18
|
def initialize(time, block)
|
13
19
|
@time = time
|
14
20
|
@block = block
|
15
21
|
end
|
16
22
|
|
23
|
+
# @attribute [Float] The time at which the block should be called.
|
24
|
+
attr :time
|
25
|
+
|
26
|
+
# @attribute [Proc | Nil] The block to call when the timer fires.
|
27
|
+
attr :block
|
28
|
+
|
29
|
+
# Compare the handle with another handle.
|
30
|
+
#
|
31
|
+
# @parameter other [Handle] The other handle to compare with.
|
32
|
+
# @returns [Boolean] Whether the handle is less than the other handle.
|
17
33
|
def < other
|
18
34
|
@time < other.time
|
19
35
|
end
|
20
36
|
|
37
|
+
# Compare the handle with another handle.
|
38
|
+
#
|
39
|
+
# @parameter other [Handle] The other handle to compare with.
|
40
|
+
# @returns [Boolean] Whether the handle is greater than the other handle.
|
21
41
|
def > other
|
22
42
|
@time > other.time
|
23
43
|
end
|
24
44
|
|
25
|
-
|
26
|
-
attr :block
|
27
|
-
|
45
|
+
# Invoke the block.
|
28
46
|
def call(...)
|
29
47
|
@block.call(...)
|
30
48
|
end
|
31
49
|
|
50
|
+
# Cancel the timer.
|
32
51
|
def cancel!
|
33
52
|
@block = nil
|
34
53
|
end
|
35
54
|
|
55
|
+
# @returns [Boolean] Whether the timer has been cancelled.
|
36
56
|
def cancelled?
|
37
57
|
@block.nil?
|
38
58
|
end
|
39
59
|
end
|
40
60
|
|
61
|
+
# Initialize the timers.
|
41
62
|
def initialize
|
42
63
|
@heap = PriorityHeap.new
|
43
64
|
@scheduled = []
|
44
65
|
end
|
45
66
|
|
67
|
+
# @returns [Integer] The number of timers in the heap.
|
46
68
|
def size
|
47
69
|
flush!
|
48
70
|
|
@@ -50,7 +72,9 @@ class IO
|
|
50
72
|
end
|
51
73
|
|
52
74
|
# Schedule a block to be called at a specific time in the future.
|
75
|
+
#
|
53
76
|
# @parameter time [Float] The time at which the block should be called, relative to {#now}.
|
77
|
+
# @parameter block [Proc] The block to call.
|
54
78
|
def schedule(time, block)
|
55
79
|
handle = Handle.new(time, block)
|
56
80
|
|
@@ -60,11 +84,18 @@ class IO
|
|
60
84
|
end
|
61
85
|
|
62
86
|
# Schedule a block to be called after a specific time offset, relative to the current time as returned by {#now}.
|
87
|
+
#
|
63
88
|
# @parameter offset [#to_f] The time offset from the current time at which the block should be called.
|
89
|
+
# @yields {|now| ...} When the timer fires.
|
64
90
|
def after(offset, &block)
|
65
91
|
schedule(self.now + offset.to_f, block)
|
66
92
|
end
|
67
93
|
|
94
|
+
|
95
|
+
# Compute the time interval until the next timer fires.
|
96
|
+
#
|
97
|
+
# @parameter now [Float] The current time.
|
98
|
+
# @returns [Float | Nil] The time interval until the next timer fires, if any.
|
68
99
|
def wait_interval(now = self.now)
|
69
100
|
flush!
|
70
101
|
|
@@ -77,10 +108,14 @@ class IO
|
|
77
108
|
end
|
78
109
|
end
|
79
110
|
|
111
|
+
# @returns [Float] The current time.
|
80
112
|
def now
|
81
113
|
::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
82
114
|
end
|
83
115
|
|
116
|
+
# Fire all timers that are ready to fire.
|
117
|
+
#
|
118
|
+
# @parameter now [Float] The current time.
|
84
119
|
def fire(now = self.now)
|
85
120
|
# Flush scheduled timers into the heap:
|
86
121
|
flush!
|
@@ -101,6 +136,9 @@ class IO
|
|
101
136
|
end
|
102
137
|
end
|
103
138
|
|
139
|
+
# Flush all scheduled timers into the heap.
|
140
|
+
#
|
141
|
+
# This is a small optimization which assumes that most timers (timeouts) will be cancelled.
|
104
142
|
protected def flush!
|
105
143
|
while handle = @scheduled.pop
|
106
144
|
@heap.push(handle) unless handle.cancelled?
|
data/lib/io/event/version.rb
CHANGED
data/readme.md
CHANGED
@@ -10,7 +10,17 @@ The initial proof-of-concept [Async](https://github.com/socketry/async) was buil
|
|
10
10
|
|
11
11
|
## Usage
|
12
12
|
|
13
|
-
Please see the [project documentation](https://socketry.github.io/io-event/).
|
13
|
+
Please see the [project documentation](https://socketry.github.io/io-event/) for more details.
|
14
|
+
|
15
|
+
- [Getting Started](https://socketry.github.io/io-event/guides/getting-started/index) - This guide explains how to use `io-event` for non-blocking IO.
|
16
|
+
|
17
|
+
## Releases
|
18
|
+
|
19
|
+
Please see the [project releases](https://socketry.github.io/io-event/releases/index) for all releases.
|
20
|
+
|
21
|
+
### v1.7.5
|
22
|
+
|
23
|
+
- Fix `process_wait` race condition on EPoll that could cause a hang.
|
14
24
|
|
15
25
|
## Contributing
|
16
26
|
|
data/releases.md
ADDED
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-event
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.7.
|
4
|
+
version: 1.7.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -45,7 +45,7 @@ cert_chain:
|
|
45
45
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
46
46
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
47
47
|
-----END CERTIFICATE-----
|
48
|
-
date: 2024-
|
48
|
+
date: 2024-12-15 00:00:00.000000000 Z
|
49
49
|
dependencies: []
|
50
50
|
description:
|
51
51
|
email:
|
@@ -83,6 +83,7 @@ files:
|
|
83
83
|
- lib/io/event/version.rb
|
84
84
|
- license.md
|
85
85
|
- readme.md
|
86
|
+
- releases.md
|
86
87
|
homepage: https://github.com/socketry/io-event
|
87
88
|
licenses:
|
88
89
|
- MIT
|
metadata.gz.sig
CHANGED
Binary file
|