揭秘 Ruby "Fiber" 内部结构

Demystifying Ruby "Fiber" internals

我正在学习 Ruby Fiber,它提供了很大的灵活性,但我对 Fiber 和 Ruby.

提出了一些疑问
require 'fiber'

class MyObj
    def call_yield
      print "Prepare to Yield"
      print "foo bar"
      Fiber.yield
      print "Resumed"
      @fiber = nil
    end 

    def create_fiber
      #@fiber = Fiber.new{call_yield}
      @fiber = Fiber.new {}
      p @fiber
    end

    def update
      p @fiber.resume
    end
end
  
obj = MyObj.new
# obj.call_yield #Fiber error 
obj.create_fiber
obj.update
obj.update
  1. 当我取消注释带有 obj.call_yield 的行时,当我在 irb 会话中键入 Fiber.yield 时,Fiber 错误发生为 expected.Even,同样的错误发生。

    • 如何ruby识别当前光纤是否有效?
    • 包含 Fiber.Yield 的块的范围是什么给 Fiber.new
  2. 注意 create fiber 方法中的 #@fiber = Fiber.new{call_yield} 行仍然是有效代码。

    • 我不知道那里发生了什么,因为函数是直接调用的,而不是作为符号调用的。
    • 即使直接调用函数我在 screen.This 上也看不到任何内容显示函数内部的代码仍未启动 运行,但为什么会出现这种情况?
  3. 由于 fiber 是用 C 编写的,我没有其他来源可以消除我的疑问,因此请尽可能为每个问题提供简单的示例。

I want to know how Fiber.yield behaves when inside block that is provided to Fiber.new vs any other place in program ie)How it produces "root fiber error" elsewhere in program?

嗯,其实很简单。你需要做的就是在执行resume时修改一块全局状态。例如,将当前纤程推送到全局堆栈或类似的东西。这是表现出相同行为的假光纤 class。

class MyFiber
  class << self
    def stack
      @stack ||= []
    end
    
    def yield
      top = stack.pop
      if top.nil?
        raise 'root fiber error'
      end
      puts "running fiber #{top}"
    end
  end
  
  def initialize(&block)
    @block = block
  end
  
  def resume
    MyFiber.stack.push(@block)
    @block.call
  end
end