Skip to content

Commit 4b0cc4b

Browse files
authored
Merge pull request #168 from rage-rb/fiber-await-channels
Use different channels in `Fiber.await`
2 parents b85fbb5 + 4c41ec3 commit 4b0cc4b

3 files changed

Lines changed: 23 additions & 4 deletions

File tree

lib/rage/fiber.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ def __block_channel(force = false)
118118
"block:#{object_id}:#{@__block_channel_i}"
119119
end
120120

121+
# @private
122+
def __await_channel(force = false)
123+
@__fiber_channel_i ||= 0
124+
@__fiber_channel_i += 1 if force
125+
126+
"await:#{object_id}:#{@__fiber_channel_i}"
127+
end
128+
121129
# @private
122130
attr_accessor :__awaited_fileno
123131

@@ -148,6 +156,7 @@ class << self
148156
# @note This method should only be used when multiple fibers have to be processed in parallel. There's no need to use `Fiber.await` for single IO calls.
149157
def self.await(fibers)
150158
f, fibers = Fiber.current, Array(fibers)
159+
await_channel = f.__await_channel(true)
151160

152161
# check which fibers are alive (i.e. have yielded) and which have errored out
153162
i, err, num_wait_for = 0, nil, 0
@@ -169,7 +178,7 @@ def self.await(fibers)
169178
end
170179

171180
# wait on async fibers; resume right away if one of the fibers errors out
172-
Iodine.subscribe("await:#{f.object_id}") do |_, err|
181+
Iodine.subscribe(await_channel) do |_, err|
173182
if err == AWAIT_ERROR_MESSAGE
174183
f.resume
175184
else
@@ -179,7 +188,7 @@ def self.await(fibers)
179188
end
180189

181190
Fiber.defer(-1)
182-
Iodine.defer { Iodine.unsubscribe("await:#{f.object_id}") }
191+
Iodine.defer { Iodine.unsubscribe(await_channel) }
183192

184193
# if num_wait_for is not 0 means we exited prematurely because of an error
185194
if num_wait_for > 0

lib/rage/fiber_scheduler.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,10 @@ def fiber(&block)
130130
Thread.current[:rage_logger] = logger
131131
Fiber.current.__set_result(block.call)
132132
# send a message for `Fiber.await` to work
133-
Iodine.publish("await:#{parent.object_id}", "", Iodine::PubSub::PROCESS) if parent.alive?
133+
Iodine.publish(parent.__await_channel, "", Iodine::PubSub::PROCESS) if parent.alive?
134134
rescue Exception => e
135135
Fiber.current.__set_err(e)
136-
Iodine.publish("await:#{parent.object_id}", Fiber::AWAIT_ERROR_MESSAGE, Iodine::PubSub::PROCESS) if parent.alive?
136+
Iodine.publish(parent.__await_channel, Fiber::AWAIT_ERROR_MESSAGE, Iodine::PubSub::PROCESS) if parent.alive?
137137
end
138138
end
139139

spec/fiber_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,14 @@
183183
-> { expect(e).to be_a(StandardError) }
184184
end
185185
end
186+
187+
it "correctly processes several awaits in a row" do
188+
within_reactor do
189+
Fiber.await(Fiber.schedule { sleep 0.1 })
190+
Fiber.await(Fiber.schedule { sleep 0.2 })
191+
Fiber.await(Fiber.schedule { sleep 0.3 })
192+
193+
-> {}
194+
end
195+
end
186196
end

0 commit comments

Comments
 (0)