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/worker_pool.rb
DELETED
@@ -1,182 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Released under the MIT License.
|
4
|
-
# Copyright, 2024, by Samuel Williams.
|
5
|
-
|
6
|
-
require "etc"
|
7
|
-
|
8
|
-
module Async
|
9
|
-
# A simple work pool that offloads work to a background thread.
|
10
|
-
#
|
11
|
-
# @private
|
12
|
-
class WorkerPool
|
13
|
-
# Used to augment the scheduler to add support for blocking operations.
|
14
|
-
module BlockingOperationWait
|
15
|
-
# Wait for the given work to be executed.
|
16
|
-
#
|
17
|
-
# @public Since *Async v2.21* and *Ruby v3.4*.
|
18
|
-
# @asynchronous May be non-blocking.
|
19
|
-
#
|
20
|
-
# @parameter work [Proc] The work to execute on a background thread.
|
21
|
-
# @returns [Object] The result of the work.
|
22
|
-
def blocking_operation_wait(work)
|
23
|
-
@worker_pool.call(work)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# Execute the given work in a background thread.
|
28
|
-
class Promise
|
29
|
-
# Create a new promise.
|
30
|
-
#
|
31
|
-
# @parameter work [Proc] The work to be done.
|
32
|
-
def initialize(work)
|
33
|
-
@work = work
|
34
|
-
@state = :pending
|
35
|
-
@value = nil
|
36
|
-
@guard = ::Mutex.new
|
37
|
-
@condition = ::ConditionVariable.new
|
38
|
-
@thread = nil
|
39
|
-
end
|
40
|
-
|
41
|
-
# Execute the work and resolve the promise.
|
42
|
-
def call
|
43
|
-
work = nil
|
44
|
-
|
45
|
-
@guard.synchronize do
|
46
|
-
@thread = ::Thread.current
|
47
|
-
|
48
|
-
return unless work = @work
|
49
|
-
end
|
50
|
-
|
51
|
-
resolve(work.call)
|
52
|
-
rescue Exception => error
|
53
|
-
reject(error)
|
54
|
-
end
|
55
|
-
|
56
|
-
private def resolve(value)
|
57
|
-
@guard.synchronize do
|
58
|
-
@work = nil
|
59
|
-
@thread = nil
|
60
|
-
@value = value
|
61
|
-
@state = :resolved
|
62
|
-
@condition.broadcast
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
private def reject(error)
|
67
|
-
@guard.synchronize do
|
68
|
-
@work = nil
|
69
|
-
@thread = nil
|
70
|
-
@value = error
|
71
|
-
@state = :failed
|
72
|
-
@condition.broadcast
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
# Cancel the work and raise an exception in the background thread.
|
77
|
-
def cancel
|
78
|
-
return unless @work
|
79
|
-
|
80
|
-
@guard.synchronize do
|
81
|
-
@work = nil
|
82
|
-
@state = :cancelled
|
83
|
-
@thread&.raise(Interrupt)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Wait for the work to be done.
|
88
|
-
#
|
89
|
-
# @returns [Object] The result of the work.
|
90
|
-
def wait
|
91
|
-
@guard.synchronize do
|
92
|
-
while @state == :pending
|
93
|
-
@condition.wait(@guard)
|
94
|
-
end
|
95
|
-
|
96
|
-
if @state == :failed
|
97
|
-
raise @value
|
98
|
-
else
|
99
|
-
return @value
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# A background worker thread.
|
106
|
-
class Worker
|
107
|
-
# Create a new worker.
|
108
|
-
def initialize
|
109
|
-
@work = ::Thread::Queue.new
|
110
|
-
@thread = ::Thread.new(&method(:run))
|
111
|
-
end
|
112
|
-
|
113
|
-
# Execute work until the queue is closed.
|
114
|
-
def run
|
115
|
-
while work = @work.pop
|
116
|
-
work.call
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
# Close the worker thread.
|
121
|
-
def close
|
122
|
-
if thread = @thread
|
123
|
-
@thread = nil
|
124
|
-
thread.kill
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
# Call the work and notify the scheduler when it is done.
|
129
|
-
def call(work)
|
130
|
-
promise = Promise.new(work)
|
131
|
-
|
132
|
-
@work.push(promise)
|
133
|
-
|
134
|
-
begin
|
135
|
-
return promise.wait
|
136
|
-
ensure
|
137
|
-
promise.cancel
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
# Create a new work pool.
|
143
|
-
#
|
144
|
-
# @parameter size [Integer] The number of threads to use.
|
145
|
-
def initialize(size: Etc.nprocessors)
|
146
|
-
@ready = ::Thread::Queue.new
|
147
|
-
|
148
|
-
size.times do
|
149
|
-
@ready.push(Worker.new)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
# Close the work pool. Kills all outstanding work.
|
154
|
-
def close
|
155
|
-
if ready = @ready
|
156
|
-
@ready = nil
|
157
|
-
ready.close
|
158
|
-
|
159
|
-
while worker = ready.pop
|
160
|
-
worker.close
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
# Offload work to a thread.
|
166
|
-
#
|
167
|
-
# @parameter work [Proc] The work to be done.
|
168
|
-
def call(work)
|
169
|
-
if ready = @ready
|
170
|
-
worker = ready.pop
|
171
|
-
|
172
|
-
begin
|
173
|
-
worker.call(work)
|
174
|
-
ensure
|
175
|
-
ready.push(worker)
|
176
|
-
end
|
177
|
-
else
|
178
|
-
raise RuntimeError, "No worker available!"
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|