async 2.24.0 → 2.27.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.
data/lib/async/task.rb CHANGED
@@ -1,44 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2017-2024, by Samuel Williams.
4
+ # Copyright, 2017-2025, by Samuel Williams.
5
5
  # Copyright, 2017, by Kent Gruber.
6
6
  # Copyright, 2017, by Devin Christensen.
7
7
  # Copyright, 2020, by Patrik Wenger.
8
8
  # Copyright, 2023, by Math Ieu.
9
+ # Copyright, 2025, by Shigeru Nakajima.
9
10
 
10
11
  require "fiber"
11
12
  require "console"
12
13
 
13
14
  require_relative "node"
14
15
  require_relative "condition"
16
+ require_relative "stop"
15
17
 
16
18
  Fiber.attr_accessor :async_task
17
19
 
18
20
  module Async
19
- # Raised when a task is explicitly stopped.
20
- class Stop < Exception
21
- # Used to defer stopping the current task until later.
22
- class Later
23
- # Create a new stop later operation.
24
- #
25
- # @parameter task [Task] The task to stop later.
26
- def initialize(task)
27
- @task = task
28
- end
29
-
30
- # @returns [Boolean] Whether the task is alive.
31
- def alive?
32
- true
33
- end
34
-
35
- # Transfer control to the operation - this will stop the task.
36
- def transfer
37
- @task.stop
38
- end
39
- end
40
- end
41
-
42
21
  # Raised if a timeout occurs on a specific Fiber. Handled gracefully by `Task`.
43
22
  # @public Since *Async v1*.
44
23
  class TimeoutError < StandardError
@@ -64,6 +43,8 @@ module Async
64
43
 
65
44
  # @deprecated With no replacement.
66
45
  def self.yield
46
+ warn("`Async::Task.yield` is deprecated with no replacement.", uplevel: 1, category: :deprecated) if $VERBOSE
47
+
67
48
  Fiber.scheduler.transfer
68
49
  end
69
50
 
@@ -133,6 +114,8 @@ module Async
133
114
 
134
115
  # @deprecated Prefer {Kernel#sleep} except when compatibility with `stable-v1` is required.
135
116
  def sleep(duration = nil)
117
+ Kernel.warn("`Async::Task#sleep` is deprecated, use `Kernel#sleep` instead.", uplevel: 1, category: :deprecated) if $VERBOSE
118
+
136
119
  super
137
120
  end
138
121
 
@@ -266,7 +249,13 @@ module Async
266
249
  # If `later` is false, it means that `stop` has been invoked directly. When `later` is true, it means that `stop` is invoked by `stop_children` or some other indirect mechanism. In that case, if we encounter the "current" fiber, we can't stop it right away, as it's currently performing `#stop`. Stopping it immediately would interrupt the current stop traversal, so we need to schedule the stop to occur later.
267
250
  #
268
251
  # @parameter later [Boolean] Whether to stop the task later, or immediately.
269
- def stop(later = false)
252
+ # @parameter cause [Exception] The cause of the stop operation.
253
+ def stop(later = false, cause: $!)
254
+ # If no cause is given, we generate one from the current call stack:
255
+ unless cause
256
+ cause = Stop::Cause.for("Stopping task!")
257
+ end
258
+
270
259
  if self.stopped?
271
260
  # If the task is already stopped, a `stop` state transition re-enters the same state which is a no-op. However, we will also attempt to stop any running children too. This can happen if the children did not stop correctly the first time around. Doing this should probably be considered a bug, but it's better to be safe than sorry.
272
261
  return stopped!
@@ -280,7 +269,7 @@ module Async
280
269
  # If we are deferring stop...
281
270
  if @defer_stop == false
282
271
  # Don't stop now... but update the state so we know we need to stop later.
283
- @defer_stop = true
272
+ @defer_stop = cause
284
273
  return false
285
274
  end
286
275
 
@@ -288,19 +277,19 @@ module Async
288
277
  # If the fiber is current, and later is `true`, we need to schedule the fiber to be stopped later, as it's currently invoking `stop`:
289
278
  if later
290
279
  # If the fiber is the current fiber and we want to stop it later, schedule it:
291
- Fiber.scheduler.push(Stop::Later.new(self))
280
+ Fiber.scheduler.push(Stop::Later.new(self, cause))
292
281
  else
293
282
  # Otherwise, raise the exception directly:
294
- raise Stop, "Stopping current task!"
283
+ raise Stop, "Stopping current task!", cause: cause
295
284
  end
296
285
  else
297
286
  # If the fiber is not curent, we can raise the exception directly:
298
287
  begin
299
288
  # There is a chance that this will stop the fiber that originally called stop. If that happens, the exception handling in `#stopped` will rescue the exception and re-raise it later.
300
- Fiber.scheduler.raise(@fiber, Stop)
289
+ Fiber.scheduler.raise(@fiber, Stop, cause: cause)
301
290
  rescue FiberError
302
291
  # In some cases, this can cause a FiberError (it might be resumed already), so we schedule it to be stopped later:
303
- Fiber.scheduler.push(Stop::Later.new(self))
292
+ Fiber.scheduler.push(Stop::Later.new(self, cause))
304
293
  end
305
294
  end
306
295
  else
@@ -340,7 +329,7 @@ module Async
340
329
 
341
330
  # If we were asked to stop, we should do so now:
342
331
  if defer_stop
343
- raise Stop, "Stopping current task (was deferred)!"
332
+ raise Stop, "Stopping current task (was deferred)!", cause: defer_stop
344
333
  end
345
334
  end
346
335
  else
@@ -351,7 +340,7 @@ module Async
351
340
 
352
341
  # @returns [Boolean] Whether stop has been deferred.
353
342
  def stop_deferred?
354
- @defer_stop
343
+ !!@defer_stop
355
344
  end
356
345
 
357
346
  # Lookup the {Task} for the current fiber. Raise `RuntimeError` if none is available.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2021-2024, by Samuel Williams.
4
+ # Copyright, 2021-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "condition"
7
7
 
data/lib/async/version.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2017-2024, by Samuel Williams.
4
+ # Copyright, 2017-2025, by Samuel Williams.
5
5
 
6
6
  module Async
7
- VERSION = "2.24.0"
7
+ VERSION = "2.27.0"
8
8
  end
data/lib/async/waiter.rb CHANGED
@@ -1,17 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2022-2024, by Samuel Williams.
4
+ # Copyright, 2022-2025, by Samuel Williams.
5
5
  # Copyright, 2024, by Patrik Wenger.
6
6
 
7
7
  module Async
8
8
  # A composable synchronization primitive, which allows one task to wait for a number of other tasks to complete. It can be used in conjunction with {Semaphore} and/or {Barrier}.
9
+ # @deprecated `Async::Waiter` is deprecated, use `Async::Barrier` instead.
9
10
  class Waiter
10
11
  # Create a waiter instance.
11
12
  #
12
13
  # @parameter parent [Interface(:async) | Nil] The parent task to use for asynchronous operations.
13
14
  # @parameter finished [Async::Condition] The condition to signal when a task completes.
14
15
  def initialize(parent: nil, finished: Async::Condition.new)
16
+ warn("`Async::Waiter` is deprecated, use `Async::Barrier` instead.", uplevel: 1, category: :deprecated) if $VERBOSE
17
+
15
18
  @finished = finished
16
19
  @done = []
17
20
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2024, by Samuel Williams.
4
+ # Copyright, 2024-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "../../../async/task"
7
7
  require "metrics/provider"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2022, by Samuel Williams.
4
+ # Copyright, 2024-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "../../../async/barrier"
7
7
  require "traces/provider"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2022, by Samuel Williams.
4
+ # Copyright, 2024-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "../../../async/task"
7
7
  require "traces/provider"
data/license.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
 
3
- Copyright, 2017-2024, by Samuel Williams.
3
+ Copyright, 2017-2025, by Samuel Williams.
4
4
  Copyright, 2017, by Kent Gruber.
5
5
  Copyright, 2017, by Devin Christensen.
6
6
  Copyright, 2018, by Sokolov Yura.
@@ -27,6 +27,11 @@ Copyright, 2023, by Emil Tin.
27
27
  Copyright, 2023, by Gert Goet.
28
28
  Copyright, 2024, by Dimitar Peychinov.
29
29
  Copyright, 2024, by Jamie McCarthy.
30
+ Copyright, 2025, by Jahfer Husain.
31
+ Copyright, 2025, by Mark Montroy.
32
+ Copyright, 2025, by Shigeru Nakajima.
33
+ Copyright, 2025, by Alan Wu.
34
+ Copyright, 2025, by Shopify Inc.
30
35
 
31
36
  Permission is hereby granted, free of charge, to any person obtaining a copy
32
37
  of this software and associated documentation files (the "Software"), to deal
data/readme.md CHANGED
@@ -35,6 +35,28 @@ 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.27.0
39
+
40
+ - `Async::Task#stop` supports an optional `cause:` argument (that defaults to `$!`), which allows you to specify the cause (exception) for stopping the task.
41
+ - Add thread-safety agent context.
42
+
43
+ ### v2.26.0
44
+
45
+ - `Async::Notification#signal` now returns `true` if a task was signaled, `false` otherwise, providing better feedback for notification operations.
46
+ - `require "async/limited_queue"` is required to use `Async::LimitedQueue` without a deprecation warning. `Async::LimitedQueue` is not deprecated, but it's usage via `async/queue` is deprecated.
47
+ - `Async::Task#sleep` is deprecated with no replacement.
48
+ - `Async::Task.yield` is deprecated with no replacement.
49
+ - `Async::Scheduler#async` is deprecated, use `Async{}`, `Sync{}` or `Async::Task#async` instead.
50
+ - Agent context is now available, via the [`agent-context` gem](https://github.com/ioquatix/agent-context).
51
+ - [`Async::Barrier` Improvements](https://socketry.github.io/async/releases/index#async::barrier-improvements)
52
+ - [Introduce `Async::Queue#close`](https://socketry.github.io/async/releases/index#introduce-async::queue#close)
53
+
54
+ ### v2.25.0
55
+
56
+ - 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.
57
+ - [Use `IO::Event::WorkerPool` for Blocking Operations](https://socketry.github.io/async/releases/index#use-io::event::workerpool-for-blocking-operations)
58
+ - [Better handling of `IO#close` using `fiber_interrupt`](https://socketry.github.io/async/releases/index#better-handling-of-io#close-using-fiber_interrupt)
59
+
38
60
  ### v2.24.0
39
61
 
40
62
  - Ruby v3.1 support is dropped.
@@ -56,7 +78,7 @@ Please see the [project releases](https://socketry.github.io/async/releases/inde
56
78
 
57
79
  ### v2.19.0
58
80
 
59
- - [Async::Scheduler Debugging](https://socketry.github.io/async/releases/index#async::scheduler-debugging)
81
+ - [`Async::Scheduler` Debugging](https://socketry.github.io/async/releases/index#async::scheduler-debugging)
60
82
  - [Console Shims](https://socketry.github.io/async/releases/index#console-shims)
61
83
 
62
84
  ### v2.18.0
@@ -67,10 +89,6 @@ Please see the [project releases](https://socketry.github.io/async/releases/inde
67
89
 
68
90
  - Introduce `Async::Queue#push` and `Async::Queue#pop` for compatibility with `::Queue`.
69
91
 
70
- ### v2.16.0
71
-
72
- - [Better Handling of Async and Sync in Nested Fibers](https://socketry.github.io/async/releases/index#better-handling-of-async-and-sync-in-nested-fibers)
73
-
74
92
  ## See Also
75
93
 
76
94
  - [async-http](https://github.com/socketry/async-http) — Asynchronous HTTP client/server.
data/releases.md CHANGED
@@ -1,5 +1,119 @@
1
1
  # Releases
2
2
 
3
+ ## v2.27.0
4
+
5
+ - `Async::Task#stop` supports an optional `cause:` argument (that defaults to `$!`), which allows you to specify the cause (exception) for stopping the task.
6
+ - Add thread-safety agent context.
7
+
8
+ ## v2.26.0
9
+
10
+ - `Async::Notification#signal` now returns `true` if a task was signaled, `false` otherwise, providing better feedback for notification operations.
11
+ - `require "async/limited_queue"` is required to use `Async::LimitedQueue` without a deprecation warning. `Async::LimitedQueue` is not deprecated, but it's usage via `async/queue` is deprecated.
12
+ - `Async::Task#sleep` is deprecated with no replacement.
13
+ - `Async::Task.yield` is deprecated with no replacement.
14
+ - `Async::Scheduler#async` is deprecated, use `Async{}`, `Sync{}` or `Async::Task#async` instead.
15
+ - Agent context is now available, via the [`agent-context` gem](https://github.com/ioquatix/agent-context).
16
+
17
+ ### `Async::Barrier` Improvements
18
+
19
+ `Async::Barrier` now provides more flexible and predictable behavior for waiting on task completion:
20
+
21
+ - **Completion-order waiting**: `barrier.wait` now processes tasks in the order they complete rather than the order they were created. This provides more predictable behavior when tasks have different execution times.
22
+ - **Block-based waiting**: `barrier.wait` now accepts an optional block that yields each task as it completes, allowing for custom handling of individual tasks:
23
+
24
+ <!-- end list -->
25
+
26
+ ``` ruby
27
+ barrier = Async::Barrier.new
28
+
29
+ # Start several tasks
30
+ 3.times do |i|
31
+ barrier.async do |task|
32
+ sleep(rand * 0.1) # Random completion time
33
+ "result_#{i}"
34
+ end
35
+ end
36
+
37
+ # Wait for all tasks, processing them as they complete
38
+ barrier.wait do |task|
39
+ result = task.wait
40
+ puts "Task completed with: #{result}"
41
+ end
42
+ ```
43
+
44
+ - **Partial completion support**: The new block-based interface allows you to wait for only the first N tasks to complete:
45
+
46
+ <!-- end list -->
47
+
48
+ ``` ruby
49
+ # Wait for only the first 3 tasks to complete
50
+ count = 0
51
+ barrier.wait do |task|
52
+ task.wait
53
+ count += 1
54
+ break if count >= 3
55
+ end
56
+ ```
57
+
58
+ This makes `Async::Barrier` a superset of `Async::Waiter` functionality, providing more flexible task coordination patterns, and therrefore, `Async::Waiter` is now deprecated.
59
+
60
+ ### Introduce `Async::Queue#close`
61
+
62
+ `Async::Queue` and `Async::LimitedQueue` can now be closed, which provides better resource management and error handling:
63
+
64
+ - **New `close` method**: Both queue types now have a `close` method that prevents further items from being added and signals any waiting tasks.
65
+ - **Consistent error handling**: All queue modification methods (`push`, `enqueue`, `<<`) now raise `Async::Queue::ClosedError` when called on a closed queue.
66
+ - **Waiting task signaling**: When a queue is closed, any tasks waiting on `dequeue` (for regular queues) or `enqueue` (for limited queues) are properly signaled and can complete.
67
+
68
+ <!-- end list -->
69
+
70
+ ``` ruby
71
+ queue = Async::Queue.new
72
+
73
+ # Start a task waiting for items:
74
+ waiting_task = Async do
75
+ queue.dequeue
76
+ end
77
+
78
+ # Close the queue - this signals the waiting task
79
+ queue.close
80
+
81
+ # These will raise Async::Queue::ClosedError
82
+ queue.push(:item) # => raises ClosedError
83
+ queue.enqueue(:item) # => raises ClosedError
84
+ queue << :item # => raises ClosedError
85
+
86
+ # Dequeue returns nil when closed and empty
87
+ queue.dequeue # => nil
88
+ ```
89
+
90
+ ## v2.25.0
91
+
92
+ - 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.
93
+
94
+ ### Use `IO::Event::WorkerPool` for Blocking Operations
95
+
96
+ The `Async::WorkerPool` implementation has been removed in favor of using `IO::Event::WorkerPool` directly. This change simplifies the codebase by delegating worker pool functionality to the `io-event` gem, which provides a more efficient and well-tested implementation.
97
+
98
+ To enable the worker pool, you can set the `ASYNC_SCHEDULER_WORKER_POOL` environment variable to `true`. This will allow the scheduler to use a worker pool for blocking operations, which can help improve performance in applications that perform a lot of CPU-bound operations (e.g. `rb_nogvl`).
99
+
100
+ ### Better handling of `IO#close` using `fiber_interrupt`
101
+
102
+ `IO#close` interrupts fibers that are waiting on the IO using the new `fiber_interrupt` hook introduced in Ruby 3.5/4.0. This means that if you close an IO while a fiber is waiting on it, the fiber will be interrupted and will raise an `IOError`. This is a change from previous versions of Ruby, where closing an IO would not interrupt fibers waiting on it, and would instead interrupt the entire event loop (essentially a bug).
103
+
104
+ ``` ruby
105
+ r, w = IO.pipe
106
+
107
+ Async do
108
+ child = Async do
109
+ r.gets
110
+ end
111
+
112
+ r.close # This will interrupt the child fiber.
113
+ child.wait # This will raise an `IOError` because the IO was closed.
114
+ end
115
+ ```
116
+
3
117
  ## v2.24.0
4
118
 
5
119
  - Ruby v3.1 support is dropped.
@@ -7,7 +121,7 @@
7
121
 
8
122
  ### Flexible Timeouts
9
123
 
10
- When {ruby Async::Scheduler\#with\_timeout} is invoked with a block, it can receive a {ruby Async::Timeout} instance. This allows you to adjust or cancel the timeout while the block is executing. This is useful for long-running tasks that may need to adjust their timeout based on external factors.
124
+ When `Async::Scheduler#with_timeout` is invoked with a block, it can receive a `Async::Timeout` instance. This allows you to adjust or cancel the timeout while the block is executing. This is useful for long-running tasks that may need to adjust their timeout based on external factors.
11
125
 
12
126
  ``` ruby
13
127
  Async do
@@ -81,7 +195,7 @@ To take advantage of this feature, you will need to introduce your own `config/t
81
195
 
82
196
  ## v2.19.0
83
197
 
84
- ### Async::Scheduler Debugging
198
+ ### `Async::Scheduler` Debugging
85
199
 
86
200
  Occasionally on issues, I encounter people asking for help and I need more information. Pressing Ctrl-C to exit a hung program is common, but it usually doesn't provide enough information to diagnose the problem. Setting the `CONSOLE_LEVEL=debug` environment variable will now print additional information about the scheduler when you interrupt it, including a backtrace of the current tasks.
87
201
 
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,10 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.24.0
4
+ version: 2.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
+ - Shopify Inc.
8
9
  - Bruno Sutic
9
10
  - Jeremy Jung
10
11
  - Olle Jonsson
@@ -13,21 +14,25 @@ authors:
13
14
  - Emil Tin
14
15
  - Jamie McCarthy
15
16
  - Kent Gruber
17
+ - Alan Wu
16
18
  - Brian Morearty
17
19
  - Colin Kelley
18
20
  - Dimitar Peychinov
19
21
  - Gert Goet
22
+ - Jahfer Husain
20
23
  - Jiang Jinyang
21
24
  - Julien Portalier
22
25
  - Jun Jiang
23
26
  - Ken Muryoi
24
27
  - Leon Löchner
28
+ - Mark Montroy
25
29
  - Masafumi Okura
26
30
  - Masayuki Yamamoto
27
31
  - Math Ieu
28
32
  - Ryan Musgrave
29
33
  - Salim Semaoune
30
34
  - Shannon Skipper
35
+ - Shigeru Nakajima
31
36
  - Sokolov Yura
32
37
  - Stefan Wrobel
33
38
  - Trevor Turk
@@ -62,7 +67,7 @@ cert_chain:
62
67
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
63
68
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
64
69
  -----END CERTIFICATE-----
65
- date: 2025-05-03 00:00:00.000000000 Z
70
+ date: 1980-01-02 00:00:00.000000000 Z
66
71
  dependencies:
67
72
  - !ruby/object:Gem::Dependency
68
73
  name: console
@@ -98,46 +103,47 @@ dependencies:
98
103
  requirements:
99
104
  - - "~>"
100
105
  - !ruby/object:Gem::Version
101
- version: '1.9'
106
+ version: '1.11'
102
107
  type: :runtime
103
108
  prerelease: false
104
109
  version_requirements: !ruby/object:Gem::Requirement
105
110
  requirements:
106
111
  - - "~>"
107
112
  - !ruby/object:Gem::Version
108
- version: '1.9'
113
+ version: '1.11'
109
114
  - !ruby/object:Gem::Dependency
110
- name: traces
115
+ name: metrics
111
116
  requirement: !ruby/object:Gem::Requirement
112
117
  requirements:
113
118
  - - "~>"
114
119
  - !ruby/object:Gem::Version
115
- version: '0.15'
120
+ version: '0.12'
116
121
  type: :runtime
117
122
  prerelease: false
118
123
  version_requirements: !ruby/object:Gem::Requirement
119
124
  requirements:
120
125
  - - "~>"
121
126
  - !ruby/object:Gem::Version
122
- version: '0.15'
127
+ version: '0.12'
123
128
  - !ruby/object:Gem::Dependency
124
- name: metrics
129
+ name: traces
125
130
  requirement: !ruby/object:Gem::Requirement
126
131
  requirements:
127
132
  - - "~>"
128
133
  - !ruby/object:Gem::Version
129
- version: '0.12'
134
+ version: '0.15'
130
135
  type: :runtime
131
136
  prerelease: false
132
137
  version_requirements: !ruby/object:Gem::Requirement
133
138
  requirements:
134
139
  - - "~>"
135
140
  - !ruby/object:Gem::Version
136
- version: '0.12'
141
+ version: '0.15'
137
142
  executables: []
138
143
  extensions: []
139
144
  extra_rdoc_files: []
140
145
  files:
146
+ - agent.md
141
147
  - lib/async.rb
142
148
  - lib/async/barrier.md
143
149
  - lib/async/barrier.rb
@@ -155,14 +161,13 @@ files:
155
161
  - lib/async/scheduler.rb
156
162
  - lib/async/semaphore.md
157
163
  - lib/async/semaphore.rb
164
+ - lib/async/stop.rb
158
165
  - lib/async/task.md
159
166
  - lib/async/task.rb
160
167
  - lib/async/timeout.rb
161
168
  - lib/async/variable.rb
162
169
  - lib/async/version.rb
163
- - lib/async/waiter.md
164
170
  - lib/async/waiter.rb
165
- - lib/async/worker_pool.rb
166
171
  - lib/kernel/async.rb
167
172
  - lib/kernel/sync.rb
168
173
  - lib/metrics/provider/async.rb
@@ -187,14 +192,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
187
192
  requirements:
188
193
  - - ">="
189
194
  - !ruby/object:Gem::Version
190
- version: '3.1'
195
+ version: '3.2'
191
196
  required_rubygems_version: !ruby/object:Gem::Requirement
192
197
  requirements:
193
198
  - - ">="
194
199
  - !ruby/object:Gem::Version
195
200
  version: '0'
196
201
  requirements: []
197
- rubygems_version: 3.6.2
202
+ rubygems_version: 3.6.7
198
203
  specification_version: 4
199
204
  summary: A concurrency framework for Ruby.
200
205
  test_files: []
metadata.gz.sig CHANGED
Binary file
data/lib/async/waiter.md DELETED
@@ -1,50 +0,0 @@
1
- A synchronization primitive, which allows you to wait for tasks to complete in order of completion. This is useful for implementing a task pool, where you want to wait for the first task to complete, and then cancel the rest.
2
-
3
- If you try to wait for more things than you have added, you will deadlock.
4
-
5
- ## Example
6
-
7
- ~~~ ruby
8
- require 'async'
9
- require 'async/semaphore'
10
- require 'async/barrier'
11
- require 'async/waiter'
12
-
13
- Sync do
14
- barrier = Async::Barrier.new
15
- waiter = Async::Waiter.new(parent: barrier)
16
- semaphore = Async::Semaphore.new(2, parent: waiter)
17
-
18
- # Sleep sort the numbers:
19
- generator = Async do
20
- while true
21
- semaphore.async do |task|
22
- number = rand(1..10)
23
- sleep(number)
24
- end
25
- end
26
- end
27
-
28
- numbers = []
29
-
30
- 4.times do
31
- # Wait for all the numbers to be sorted:
32
- numbers << waiter.wait
33
- end
34
-
35
- # Don't generate any more numbers:
36
- generator.stop
37
-
38
- # Stop all tasks which we don't care about:
39
- barrier.stop
40
-
41
- Console.info("Smallest", numbers)
42
- end
43
- ~~~
44
-
45
- ### Output
46
-
47
- ~~~
48
- 0.0s info: Smallest
49
- | [3, 3, 1, 2]
50
- ~~~