async 2.29.0 → 2.30.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: 643f4000360902d473fec7d3c35dfa4d810499a7ee2d419bb6a44e185e4ce9a6
4
- data.tar.gz: fd8150c4df0e9834259c612811856764dde221f3e21a58cb33ae7a9903822f8a
3
+ metadata.gz: 1423e2d1cc2a1e1aec71d5e70640a0b8c8069d6a2b2af9da63f7bed3d0c9d548
4
+ data.tar.gz: 2529e362cd8141d9fa0d8a6ea29fd0d74298630cdd8d4034633c20365a2c5491
5
5
  SHA512:
6
- metadata.gz: 39886cbaf6b6d9a10522956c67d2c5228e22aeefe27104456f3e767441b43b13887ddb41c71e7bc2cffab7956e17117a9e0a8df64d585ecbfe532a87c2f2d592
7
- data.tar.gz: b282710c3ce0fc5db35b7de431fa7d8121c9ca3d2ef4ccb1b0c5cafc26a84162eff01aae53b1b267683d8a0c635a991afae54e4d73d3cf7c2a8b23e2e8d32cdf
6
+ metadata.gz: 3455b22a4ea6a6e438e1da05ab9c4f5e7cf4d7f8f465138814c71743b2a6d7c1b1525cc3bb13b065b0aa67d0a57d5409d23cc101c61bd026c6ace345919f0005
7
+ data.tar.gz: fb21c61222c5067d272f8e5b845fcdef9ce2f99ab831cebf6575e94068b5e22f365569a2b2af1c5ec704b7e1bf53de93ef4c6143c014e5d77f9995908761b975
checksums.yaml.gz.sig CHANGED
Binary file
@@ -39,12 +39,24 @@ module Async
39
39
  condition.signal
40
40
  end
41
41
 
42
- def wait_for_value(mutex)
43
- condition.wait(mutex)
42
+ def wait_for_value(mutex, timeout = nil)
43
+ condition.wait(mutex, timeout)
44
44
  return self.value
45
45
  end
46
+
47
+ # Invalidate this waiter, making it unusable and detectable as abandoned.
48
+ def invalidate!
49
+ self.fiber = nil
50
+ end
51
+
52
+ # Check if this waiter has been invalidated.
53
+ def valid?
54
+ self.fiber&.alive?
55
+ end
46
56
  end
47
57
 
58
+ private_constant :Waiter
59
+
48
60
  # Create a new priority queue.
49
61
  #
50
62
  # @parameter parent [Interface(:async) | Nil] The parent task to use for async operations.
@@ -64,16 +76,18 @@ module Async
64
76
  @mutex.synchronize do
65
77
  @closed = true
66
78
 
67
- # Signal all waiting fibers with nil, skipping dead ones:
79
+ # Signal all waiting fibers with nil, skipping dead/invalid ones:
68
80
  while waiter = @waiting.pop
69
- if waiter.fiber.alive?
70
- waiter.signal(nil)
71
- end
72
- # Dead waiter discarded, continue to next one.
81
+ waiter.signal(nil)
73
82
  end
74
83
  end
75
84
  end
76
85
 
86
+ # @returns [Boolean] Whether the queue is closed.
87
+ def closed?
88
+ @closed
89
+ end
90
+
77
91
  # @attribute [Array] The items in the queue.
78
92
  attr :items
79
93
 
@@ -105,14 +119,14 @@ module Async
105
119
 
106
120
  @items << item
107
121
 
108
- # Wake up the highest priority waiter if any, skipping dead waiters:
122
+ # Wake up the highest priority waiter if any, skipping dead/invalid waiters:
109
123
  while waiter = @waiting.pop
110
- if waiter.fiber.alive?
124
+ if waiter.valid?
111
125
  value = @items.shift
112
126
  waiter.signal(value)
113
127
  break
114
128
  end
115
- # Dead waiter discarded, try next one.
129
+ # Dead/invalid waiter discarded, try next one.
116
130
  end
117
131
  end
118
132
  end
@@ -133,26 +147,27 @@ module Async
133
147
 
134
148
  @items.concat(items)
135
149
 
136
- # Wake up waiting fibers in priority order, skipping dead waiters:
150
+ # Wake up waiting fibers in priority order, skipping dead/invalid waiters:
137
151
  while !@items.empty? && (waiter = @waiting.pop)
138
- if waiter.fiber.alive?
152
+ if waiter.valid?
139
153
  value = @items.shift
140
154
  waiter.signal(value)
141
155
  end
142
- # Dead waiter discarded, continue to next one.
156
+ # Dead/invalid waiter discarded, continue to next one.
143
157
  end
144
158
  end
145
159
  end
146
160
 
147
161
  # Remove and return the next item from the queue.
148
162
  #
149
- # If the queue is empty, this method will block until an item is available.
163
+ # If the queue is empty, this method will block until an item is available or timeout expires.
150
164
  # Fibers are served in priority order, with higher priority fibers receiving
151
165
  # items first.
152
166
  #
153
167
  # @parameter priority [Numeric] The priority of this consumer (higher = served first).
154
- # @returns [Object] The next item in the queue.
155
- def dequeue(priority: 0)
168
+ # @parameter timeout [Numeric, nil] Maximum time to wait for an item. If nil, waits indefinitely. If 0, returns immediately.
169
+ # @returns [Object, nil] The next item in the queue, or nil if timeout expires.
170
+ def dequeue(priority: 0, timeout: nil)
156
171
  @mutex.synchronize do
157
172
  # If queue is closed and empty, return nil immediately:
158
173
  if @closed && @items.empty?
@@ -167,25 +182,34 @@ module Async
167
182
  end
168
183
  end
169
184
 
185
+ # Handle immediate timeout (non-blocking)
186
+ return nil if timeout == 0
187
+
170
188
  # Need to wait - create our own condition variable and add to waiting queue:
171
189
  sequence = @sequence
172
190
  @sequence += 1
173
191
 
174
192
  condition = ConditionVariable.new
175
- waiter = Waiter.new(Fiber.current, priority, sequence, condition, nil)
176
- @waiting.push(waiter)
177
193
 
178
- # Wait for our specific condition variable to be signaled:
179
- # The mutex is released during wait, reacquired after:
180
- return waiter.wait_for_value(@mutex)
194
+ begin
195
+ waiter = Waiter.new(Fiber.current, priority, sequence, condition, nil)
196
+ @waiting.push(waiter)
197
+
198
+ # Wait for our specific condition variable to be signaled:
199
+ return waiter.wait_for_value(@mutex, timeout)
200
+ ensure
201
+ waiter&.invalidate!
202
+ end
181
203
  end
182
204
  end
183
205
 
184
206
  # Compatibility with {::Queue#pop}.
185
207
  #
186
208
  # @parameter priority [Numeric] The priority of this consumer.
187
- def pop(priority: 0)
188
- self.dequeue(priority: priority)
209
+ # @parameter timeout [Numeric, nil] Maximum time to wait for an item. If nil, waits indefinitely. If 0, returns immediately.
210
+ # @returns [Object, nil] The dequeued item, or nil if timeout expires.
211
+ def pop(priority: 0, timeout: nil)
212
+ self.dequeue(priority: priority, timeout: timeout)
189
213
  end
190
214
 
191
215
  # Process each item in the queue.
data/lib/async/queue.rb CHANGED
@@ -73,13 +73,17 @@ module Async
73
73
  end
74
74
 
75
75
  # Remove and return the next item from the queue.
76
- def dequeue
77
- @delegate.pop
76
+ # @parameter timeout [Numeric, nil] Maximum time to wait for an item. If nil, waits indefinitely. If 0, returns immediately.
77
+ # @returns [Object, nil] The dequeued item, or nil if timeout expires.
78
+ def dequeue(timeout: nil)
79
+ @delegate.pop(timeout: timeout)
78
80
  end
79
81
 
80
82
  # Compatibility with {::Queue#pop}.
81
- def pop(...)
82
- @delegate.pop(...)
83
+ # @parameter timeout [Numeric, nil] Maximum time to wait for an item. If nil, waits indefinitely. If 0, returns immediately.
84
+ # @returns [Object, nil] The dequeued item, or nil if timeout expires.
85
+ def pop(timeout: nil)
86
+ @delegate.pop(timeout: timeout)
83
87
  end
84
88
 
85
89
  # Process each item in the queue.
data/lib/async/version.rb CHANGED
@@ -4,5 +4,5 @@
4
4
  # Copyright, 2017-2025, by Samuel Williams.
5
5
 
6
6
  module Async
7
- VERSION = "2.29.0"
7
+ VERSION = "2.30.0"
8
8
  end
data/readme.md CHANGED
@@ -35,6 +35,13 @@ Please see the [project documentation](https://socketry.github.io/async/) for mo
35
35
 
36
36
  Please see the [project releases](https://socketry.github.io/async/releases/index) for all releases.
37
37
 
38
+ ### v2.30.0
39
+
40
+ - Add timeout support to `Async::Queue#dequeue` and `Async::Queue#pop` methods.
41
+ - Add timeout support to `Async::PriorityQueue#dequeue` and `Async::PriorityQueue#pop` methods.
42
+ - Add `closed?` method to `Async::PriorityQueue` for full queue interface compatibility.
43
+ - Support non-blocking operations using `timeout: 0` parameter.
44
+
38
45
  ### v2.29.0
39
46
 
40
47
  This release introduces thread-safety as a core concept of Async. Many core classes now have thread-safe guarantees, allowing them to be used safely across multiple threads.
@@ -85,12 +92,6 @@ This release introduces thread-safety as a core concept of Async. Many core clas
85
92
  - [`Async::Barrier` Improvements](https://socketry.github.io/async/releases/index#async::barrier-improvements)
86
93
  - [Introduce `Async::Queue#close`](https://socketry.github.io/async/releases/index#introduce-async::queue#close)
87
94
 
88
- ### v2.25.0
89
-
90
- - Added support for `io_select` hook in the fiber scheduler, allowing non-blocking `IO.select` operations. This enables better integration with code that uses `IO.select` for multiplexing IO operations.
91
- - [Use `IO::Event::WorkerPool` for Blocking Operations](https://socketry.github.io/async/releases/index#use-io::event::workerpool-for-blocking-operations)
92
- - [Better handling of `IO#close` using `fiber_interrupt`](https://socketry.github.io/async/releases/index#better-handling-of-io#close-using-fiber_interrupt)
93
-
94
95
  ## See Also
95
96
 
96
97
  - [async-http](https://github.com/socketry/async-http) — Asynchronous HTTP client/server.
data/releases.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Releases
2
2
 
3
+ ## v2.30.0
4
+
5
+ - Add timeout support to `Async::Queue#dequeue` and `Async::Queue#pop` methods.
6
+ - Add timeout support to `Async::PriorityQueue#dequeue` and `Async::PriorityQueue#pop` methods.
7
+ - Add `closed?` method to `Async::PriorityQueue` for full queue interface compatibility.
8
+ - Support non-blocking operations using `timeout: 0` parameter.
9
+
3
10
  ## v2.29.0
4
11
 
5
12
  This release introduces thread-safety as a core concept of Async. Many core classes now have thread-safe guarantees, allowing them to be used safely across multiple threads.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.29.0
4
+ version: 2.30.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
metadata.gz.sig CHANGED
Binary file