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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/agent.md +47 -0
- data/lib/async/barrier.md +0 -1
- data/lib/async/barrier.rb +30 -9
- data/lib/async/clock.rb +1 -1
- data/lib/async/condition.rb +3 -1
- data/lib/async/limited_queue.rb +7 -1
- data/lib/async/list.rb +16 -8
- data/lib/async/node.rb +2 -0
- data/lib/async/notification.rb +5 -3
- data/lib/async/queue.rb +52 -2
- data/lib/async/reactor.rb +3 -1
- data/lib/async/scheduler.rb +75 -7
- data/lib/async/stop.rb +82 -0
- data/lib/async/task.rb +21 -32
- data/lib/async/variable.rb +1 -1
- data/lib/async/version.rb +2 -2
- data/lib/async/waiter.rb +4 -1
- data/lib/metrics/provider/async/task.rb +1 -1
- data/lib/traces/provider/async/barrier.rb +1 -1
- data/lib/traces/provider/async/task.rb +1 -1
- data/license.md +6 -1
- data/readme.md +23 -5
- data/releases.md +116 -2
- data.tar.gz.sig +0 -0
- metadata +19 -14
- metadata.gz.sig +0 -0
- data/lib/async/waiter.md +0 -50
- data/lib/async/worker_pool.rb +0 -182
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-
|
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
|
-
|
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 =
|
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
|
-
|
343
|
+
!!@defer_stop
|
355
344
|
end
|
356
345
|
|
357
346
|
# Lookup the {Task} for the current fiber. Raise `RuntimeError` if none is available.
|
data/lib/async/variable.rb
CHANGED
data/lib/async/version.rb
CHANGED
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-
|
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
|
|
data/license.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# MIT License
|
2
2
|
|
3
|
-
Copyright, 2017-
|
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
|
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.
|
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:
|
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.
|
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.
|
113
|
+
version: '1.11'
|
109
114
|
- !ruby/object:Gem::Dependency
|
110
|
-
name:
|
115
|
+
name: metrics
|
111
116
|
requirement: !ruby/object:Gem::Requirement
|
112
117
|
requirements:
|
113
118
|
- - "~>"
|
114
119
|
- !ruby/object:Gem::Version
|
115
|
-
version: '0.
|
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.
|
127
|
+
version: '0.12'
|
123
128
|
- !ruby/object:Gem::Dependency
|
124
|
-
name:
|
129
|
+
name: traces
|
125
130
|
requirement: !ruby/object:Gem::Requirement
|
126
131
|
requirements:
|
127
132
|
- - "~>"
|
128
133
|
- !ruby/object:Gem::Version
|
129
|
-
version: '0.
|
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.
|
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.
|
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.
|
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
|
-
~~~
|