io-event 1.5.0 → 1.6.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
2
  SHA256:
3
- metadata.gz: aa82f1290f00aaf8cadbae8346653a4291f2e14d4ffec326972507ee69859720
4
- data.tar.gz: aaed781d30c999d4cab7be1b3e4056e339d55256802b7c12c9d66fd46d64dcce
3
+ metadata.gz: 601c49b58251e4e77e4cfaf2140e834c038ca811c7980dd034f2160440ef7cb2
4
+ data.tar.gz: db9a38fc187e6a79d70b38fbb778670ba34d7263f15857aa155dec529117f68c
5
5
  SHA512:
6
- metadata.gz: fa1d7ee55e1af2a88d377366b8322a88fddd3c6d918edbcd636ce032e9bcfe98200fae4eb2ff192cbd8c469502a6390f6422ab210bfcd115adff666f6dcd9ca0
7
- data.tar.gz: c0e15ecb8c57b9b7d19bf0a4ab7d56b34da728b53608b767d11ae468eadb086237058e75586bc146caac11883197f3cbf9ed491dc86c6e95dc2f3b6e77930a53
6
+ metadata.gz: 2fd3ca69bacc5f41c70b5502224c2baf5b66d394ea8205dfd8f4da85d61f1d5d0aae1406e649394fbd9fbb7a4b275a8502b65548341c0e2e61e8d4e3b6147ff0
7
+ data.tar.gz: 239deeba624f0d2a5bdffdd6ceb2d6660317b7564da5c466887f6cee1492b30fe1828f7012e65d19c59ecd997ed625d5effb7e24522b51a7e24324363590d7a2
checksums.yaml.gz.sig CHANGED
Binary file
@@ -152,6 +152,7 @@ void close_internal(struct IO_Event_Selector_EPoll *selector)
152
152
  IO_Event_Interrupt_close(&selector->interrupt);
153
153
  }
154
154
  }
155
+
155
156
  static
156
157
  void IO_Event_Selector_EPoll_Type_free(void *_selector)
157
158
  {
@@ -371,7 +371,7 @@ VALUE IO_Event_Selector_KQueue_loop(VALUE self) {
371
371
 
372
372
  VALUE IO_Event_Selector_KQueue_idle_duration(VALUE self) {
373
373
  struct IO_Event_Selector_KQueue *selector = NULL;
374
- TypedData_Get_Struct(self, struct IO_Event_Selector_EPoll, &IO_Event_Selector_KQueue_Type, selector);
374
+ TypedData_Get_Struct(self, struct IO_Event_Selector_KQueue, &IO_Event_Selector_KQueue_Type, selector);
375
375
 
376
376
  double duration = selector->idle_duration.tv_sec + (selector->idle_duration.tv_nsec / 1000000000.0);
377
377
 
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2021, by Wander Hillen.
5
+ # Copyright, 2021-2024, by Samuel Williams.
6
+
7
+ class IO
8
+ module Event
9
+ # A priority queue implementation using a standard binary minheap. It uses straight comparison
10
+ # of its contents to determine priority.
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
+ # Left here for reference, but unused.
88
+ # def swap(i, j)
89
+ # @contents[i], @contents[j] = @contents[j], @contents[i]
90
+ # end
91
+
92
+ def bubble_up(index)
93
+ parent_index = (index - 1) / 2 # watch out, integer division!
94
+
95
+ while index > 0 && @contents[index] < @contents[parent_index]
96
+ # if the node has a smaller value than its parent, swap these nodes
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.
100
+ # swap(index, parent_index)
101
+ @contents[index], @contents[parent_index] = @contents[parent_index], @contents[index]
102
+
103
+ index = parent_index
104
+ parent_index = (index - 1) / 2 # watch out, integer division!
105
+ end
106
+ end
107
+
108
+ def bubble_down(index)
109
+ swap_value = 0
110
+ swap_index = nil
111
+
112
+ while true
113
+ left_index = (2 * index) + 1
114
+ left_value = @contents[left_index]
115
+
116
+ if left_value.nil?
117
+ # This node has no children so it can't bubble down any further.
118
+ # We're done here!
119
+ return
120
+ end
121
+
122
+ # Determine which of the child nodes has the smallest value:
123
+ right_index = left_index + 1
124
+ right_value = @contents[right_index]
125
+
126
+ if right_value.nil? or right_value > left_value
127
+ swap_value = left_value
128
+ swap_index = left_index
129
+ else
130
+ swap_value = right_value
131
+ swap_index = right_index
132
+ end
133
+
134
+ if @contents[index] < swap_value
135
+ # No need to swap, the minheap invariant is already satisfied:
136
+ return
137
+ else
138
+ # 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:
139
+ # swap(index, swap_index)
140
+ @contents[index], @contents[swap_index] = @contents[swap_index], @contents[index]
141
+
142
+ index = swap_index
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2021-2023, by Samuel Williams.
4
+ # Copyright, 2021-2024, by Samuel Williams.
5
5
  # Copyright, 2023, by Math Ieu.
6
6
 
7
7
  require_relative '../interrupt'
@@ -422,6 +422,8 @@ module IO::Event
422
422
 
423
423
  if duration && duration > 0.0
424
424
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
425
+ else
426
+ @idle_duration = 0.0
425
427
  end
426
428
 
427
429
  # We need to handle interrupts on blocking IO. Every other implementation uses EINTR, but that doesn't work with `::IO.select` as it will retry the call on EINTR.
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2024, by Samuel Williams.
5
+
6
+ require_relative 'priority_heap'
7
+
8
+ class IO
9
+ module Event
10
+ class Timers
11
+ class Handle
12
+ def initialize(offset, block)
13
+ @offset = offset
14
+ @block = block
15
+ end
16
+
17
+ def < other
18
+ @offset < other.offset
19
+ end
20
+
21
+ def > other
22
+ @offset > other.offset
23
+ end
24
+
25
+ attr :offset
26
+ attr :block
27
+
28
+ def call(...)
29
+ @block.call(...)
30
+ end
31
+
32
+ def cancel!
33
+ @block = nil
34
+ end
35
+
36
+ def cancelled?
37
+ @block.nil?
38
+ end
39
+ end
40
+
41
+ def initialize
42
+ @heap = PriorityHeap.new
43
+ @scheduled = []
44
+ end
45
+
46
+ def size
47
+ flush!
48
+
49
+ return @heap.size
50
+ end
51
+
52
+ def schedule(offset, block)
53
+ handle = Handle.new(offset, block)
54
+ @scheduled << handle
55
+
56
+ return handle
57
+ end
58
+
59
+ def after(timeout, &block)
60
+ schedule(now + timeout, block)
61
+ end
62
+
63
+ def wait_interval(now = self.now)
64
+ flush!
65
+
66
+ while handle = @heap.peek
67
+ if handle.cancelled?
68
+ @heap.pop
69
+ else
70
+ return handle.offset - now
71
+ end
72
+ end
73
+ end
74
+
75
+ def now
76
+ ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
77
+ end
78
+
79
+ def fire(now = self.now)
80
+ # Flush scheduled timers into the heap:
81
+ flush!
82
+
83
+ # Get the earliest timer:
84
+ while handle = @heap.peek
85
+ if handle.cancelled?
86
+ @heap.pop
87
+ elsif handle.offset <= now
88
+ # Remove the earliest timer from the heap:
89
+ @heap.pop
90
+
91
+ # Call the block:
92
+ handle.call(now)
93
+ else
94
+ break
95
+ end
96
+ end
97
+ end
98
+
99
+ protected def flush!
100
+ while handle = @scheduled.pop
101
+ @heap.push(handle) unless handle.cancelled?
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -5,6 +5,6 @@
5
5
 
6
6
  class IO
7
7
  module Event
8
- VERSION = "1.5.0"
8
+ VERSION = "1.6.0"
9
9
  end
10
10
  end
data/lib/io/event.rb CHANGED
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2021-2023, by Samuel Williams.
4
+ # Copyright, 2021-2024, by Samuel Williams.
5
5
 
6
6
  require_relative 'event/version'
7
7
  require_relative 'event/selector'
8
+ require_relative 'event/timers'
8
9
 
9
10
  begin
10
11
  require 'IO_Event'
data/license.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # MIT License
2
2
 
3
+ Copyright, 2021, by Wander Hillen.
3
4
  Copyright, 2021-2024, by Samuel Williams.
4
5
  Copyright, 2021, by Delton Ding.
5
6
  Copyright, 2021-2024, by Benoit Daloze.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,11 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: io-event
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  - Math Ieu
9
+ - Wander Hillen
9
10
  - Benoit Daloze
10
11
  - Bruno Sutic
11
12
  - Alex Matchneer
@@ -43,7 +44,7 @@ cert_chain:
43
44
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
44
45
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
45
46
  -----END CERTIFICATE-----
46
- date: 2024-03-04 00:00:00.000000000 Z
47
+ date: 2024-06-03 00:00:00.000000000 Z
47
48
  dependencies: []
48
49
  description:
49
50
  email:
@@ -72,10 +73,12 @@ files:
72
73
  - lib/io/event.rb
73
74
  - lib/io/event/debug/selector.rb
74
75
  - lib/io/event/interrupt.rb
76
+ - lib/io/event/priority_heap.rb
75
77
  - lib/io/event/selector.rb
76
78
  - lib/io/event/selector/nonblock.rb
77
79
  - lib/io/event/selector/select.rb
78
80
  - lib/io/event/support.rb
81
+ - lib/io/event/timers.rb
79
82
  - lib/io/event/version.rb
80
83
  - license.md
81
84
  - readme.md
metadata.gz.sig CHANGED
Binary file