Skip to content

unit FiberMgr

em.utils/FiberMgr.em
package em.utils

from em.mcu import Common
from em.utils import ListMgr

module FiberMgr
            #   ^| manages opaque fiber objects
    type FiberBodyFxn: function(arg: uarg_t)
            #   ^| function signature of fiber body
    type Fiber: opaque
            #   ^| opaque fiber object - public specification
        host function initH(fxn: FiberBodyFxn, arg: uarg_t = 0)
            #   ^| initialize this fiber and bind its function and argument
        function getArg(): uarg_t
            #   ^| get this fiber's body function argument
        function getFxn(): FiberBodyFxn
            #   ^| get this fiber's body function
        function post()
            #   ^| make this fiber ready-to-run
        function setArg(a: uarg_t)
            #   ^| set this fiber's body function argument
        function setFxn(f: FiberBodyFxn)
            #   ^| set this fiber's body function
    end

    host function createH(fxn: FiberBodyFxn, arg: uarg_t = 0): Fiber&
            #   ^| allocate and initialize a fiber; see Fiber.initH
    function run()
            #   ^| initiate dispatch of ready-to-run fibers
private:

    def opaque Fiber
        elem: ListMgr.Element
        fxn_: FiberBodyFxn
        arg_: uarg_t
    end

    function dispatch()

    var fiberTab: Fiber[]
    var readyList: ListMgr.List

end

def em$construct() 
    readyList.initH()
end

def createH(fxn, arg)
    var fiber: Fiber& = fiberTab[fiberTab.length++]
    fiber.initH(fxn, arg)
    return fiber
end

def dispatch()
    for ;;
        break if readyList.hasElements() == 0
        auto fiber = <Fiber&>readyList.get()
        Common.GlobalInterrupts.enable()
        auto fxn = fiber.fxn_
        fxn(fiber.arg_)
        Common.GlobalInterrupts.disable()
    end   
end

def run()
    Common.Idle.wakeup()
    Common.GlobalInterrupts.enable()
    for ;;
        Common.GlobalInterrupts.disable()
        dispatch()
        Common.Idle.exec()
    end
end

def Fiber.initH(fxn, arg)
    this.elem.initH()
    this.fxn_ = fxn
    this.arg_ = arg
end

def Fiber.post()
    auto key = Common.GlobalInterrupts.disable()
    readyList.add(this.elem) if !this.elem.isActive()
    Common.GlobalInterrupts.restore(key)
end

def Fiber.getArg()
    return this.arg_
end

def Fiber.setArg(a)
    this.arg_ = a
end

def Fiber.setFxn(f)
    this.fxn_ = f
end

def Fiber.getFxn()
    return this.fxn_
end