红宝石纤维:恢复转移的纤维

问题描述 投票:5回答:2

我试图了解以下代码段的行为。我特别关注Fiber#transfer方法。

require 'fiber'

fiber2 = nil

fiber1 = Fiber.new do
  puts "In Fiber 1"                 # 3
  fiber2.transfer                   # 4
end

fiber2 = Fiber.new do
  puts "In Fiber 2"                  # 1
  fiber1.transfer                    # 2
  puts "In Fiber 2 again"            # 5
  Fiber.yield                        # 6
  puts "Fiber 2 resumed"             # 10
end

fiber3 = Fiber.new do
  puts "In Fiber 3"                  # 8
end

fiber2.resume                        # 0
fiber3.resume                        # 7
fiber2.resume                        # 9

我已经编写了代码行,并在右侧执行了预期的执行顺序。一旦fiber3.resume返回并且我调用fiber2.resume,我希望执行在fiber2内继续标记为#10的行。相反,我得到以下错误:

fiber2.rb:24:in `resume': cannot resume transferred Fiber (FiberError)
    from fiber2.rb:24:in `<main>'

这是从列表的最后一行报告的错误:fiber2.resume

ruby fibers fiber
2个回答
3
投票

似乎behavior has changed since Ruby 1.9。在1.9中,事情的工作方式与提问者假设的方式相同,后来的Ruby版本改变了#transfer的工作方式。我正在测试2.4,但这可能适用于2. *系列中的早期版本。

在1.9中,#transfer可用于在纤维之间来回跳跃。有可能在那个时候,#resume不能用于此目的。无论如何,在Ruby 2.4中你可以使用#resume从一根光纤跳到另一根光纤,然后简单地使用Fiber.yield()跳回调用者。

示例(基于问题的代码):

require 'fiber'

fiber2 = nil

fiber1 = Fiber.new do
  puts "In Fiber 1"                 # 3
  Fiber.yield                       # 4 (returns to fiber2)
end

fiber2 = Fiber.new do
  puts "In Fiber 2"                  # 1
  fiber1.resume                      # 2
  puts "In Fiber 2 again"            # 5
  Fiber.yield                        # 6 (returns to main)
  puts "Fiber 2 resumed"             # 10
end

fiber3 = Fiber.new do
  puts "In Fiber 3"                  # 8
end

fiber2.resume                        # 0
fiber3.resume                        # 7
fiber2.resume                        # 9

#transfer的用例现在似乎是当你有两根光纤(让我们称之为A和B)并希望从A到B时,你不打算在B完成之前回到A.但是,Ruby没有尾调用优化的概念,所以A仍然需要等待B完成并产生它的最终值。尽管如此,#transfer现在基本上是一张单程票。


2
投票

您可能在ruby中发现了一个错误。当您查看源代码时,它将按您描述的方式实现:

https://fossies.org/linux/misc/ruby-2.3.1.tar.gz/ruby-2.3.1/cont.c

按照传送的标志,当您传输光纤时它被设置为1,但它永远不会被重置。

IMO应在光纤增益控制或调用良率时复位。

© www.soinside.com 2019 - 2024. All rights reserved.