Skip to content

Commit 38da9a7

Browse files
committed
Barrier waits return nil or number of tasks waited on.
1 parent 7f00f35 commit 38da9a7

File tree

3 files changed

+27
-2
lines changed

3 files changed

+27
-2
lines changed

lib/async/barrier.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,17 @@ def empty?
8181
# Wait for all tasks to complete by invoking {Task#wait} on each waiting task, which may raise an error. As long as the task has completed, it will be removed from the barrier.
8282
#
8383
# @yields {|task| ...} If a block is given, the unwaited task is yielded. You must invoke {Task#wait} yourself. In addition, you may `break` if you have captured enough results.
84+
# @returns [Integer | Nil] The number of tasks which were waited for, or `nil` if there were no tasks to wait for.
8485
#
8586
# @asynchronous Will wait for tasks to finish executing.
8687
def wait
87-
while !@tasks.empty?
88+
return nil if @tasks.empty?
89+
count = 0
90+
91+
while true
8892
# Wait for a task to finish (we get the task node):
89-
return unless waiting = @finished.wait
93+
break unless waiting = @finished.wait
94+
count += 1
9095

9196
# Remove the task as it is now finishing:
9297
@tasks.remove?(waiting)
@@ -101,7 +106,11 @@ def wait
101106
# Wait for it to either complete or raise an error:
102107
task.wait
103108
end
109+
110+
break if @tasks.empty?
104111
end
112+
113+
return count
105114
end
106115

107116
# Cancel all tasks held by the barrier.

releases.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Releases
22

3+
## Unreleased
4+
5+
- `Async::Barrier#wait` now returns the number of tasks that were waited for, or `nil` if there were no tasks to wait for. This provides better feedback about the operation, and allows you to know how many tasks were involved in the wait.
6+
37
## v2.38.1
48

59
- Fix `Barrier#async` when `parent.async` yields before the child block executes. Previously, `Barrier#wait` could return early and miss tracking the task entirely, because the task had not yet appended itself to the barrier's task list.

test/async/barrier.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,18 @@
135135
end
136136
end
137137

138+
it "returns nil when there are no tasks" do
139+
expect(barrier.wait).to be_nil
140+
end
141+
142+
it "returns the number of tasks waited for" do
143+
3.times do
144+
barrier.async{}
145+
end
146+
147+
expect(barrier.wait).to be == 3
148+
end
149+
138150
it "waits even if the child task yields immediately" do
139151
class Yielder
140152
def async(*arguments, **options, &block)

0 commit comments

Comments
 (0)