io-event 1.5.1 → 1.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92dd9a674f53250bb7307226c47bfa3fc4853c8a363509fc02d99a23fcd39194
4
- data.tar.gz: 6aca8cca51546cccb4696c4744e2be05b251cb81058bc9c44ca1deb42bb1930a
3
+ metadata.gz: 601c49b58251e4e77e4cfaf2140e834c038ca811c7980dd034f2160440ef7cb2
4
+ data.tar.gz: db9a38fc187e6a79d70b38fbb778670ba34d7263f15857aa155dec529117f68c
5
5
  SHA512:
6
- metadata.gz: b12806d9e7e9c184bec13d81792f4f77ed68162e90ada118e89015aeba5571a66f6a8aa7395d40bf923c95d61438c4121cd238433ca6b3874320b60a44d09929
7
- data.tar.gz: 27c2c7d7de7b94bddb174298996192495f8edab54b42ed58cb54f61623210504db5101924dda15e6fd7dc54df81d6fdbaff44ca42608c662febba2c17d260555
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'
@@ -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.1"
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.1
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