coroutine 携程与定时一起混用

这段代码提供了一种在Lua中扩展协程(coroutine)的方法,使其具备Unity协程的特性。实现了协程的启动、等待一帧、等待固定时间、等待异步操作完成等功能,通过定时器实现。同时,代码中包含了一些特殊注意事项,如避免使用coroutine.yield,使用特定的waitforframes等待一帧等。
摘要由CSDN通过智能技术生成
--[[
-- added by wsh @ 2017-12-19
-- 协程模块:对Lua协程conroutine进行扩展,使其具有Unity侧协程的特性
-- 注意:
-- 1、主线程使用coroutine.start启动协程,协程启动以后,首次挂起时主线程继续往下执行,这里和Unity侧表现是一致的
-- 2、协程里可以再次使用coroutine.start启动协程,和在Unity侧协程中使用StartCoroutine表现一致
-- 3、协程里启动子级协程并等待其执行完毕,在Unity侧是yield return StartCoroutine,但是在Lua不需要另外启动协程,直接调用函数即可
-- 4、如果lua侧协程不使用本脚本的扩展函数,则无法实现分帧;lua侧启动协程以后不管协程函数调用栈多深,不管使用多少次本脚本扩展函数,都运行在一个协程
-- 5、使用coroutine.waitforframes(1)来等待一帧,千万不要用coroutine.yield,否则整个协程将永远不被唤醒===>***很重要,除非你在其它地方手动唤醒它
-- 6、子级协同在lua侧等同于普通函数调用,和普通函数一样可在退出函数时带任意返回值,而Unity侧协同不能获取子级协同退出时的返回值
-- 7、理论上任何协同都可以用回调方式去做,但是对于异步操作,回调方式也需要每帧去检测异步操作是否完成,消耗相差不多,而使用协同可以简单很多,清晰很多
-- 8、协程所有等待时间的操作,如coroutine.waitforseconds误差由帧率决定,循环等待时有累积误差,所以最好只是用于分帧,或者等待异步操作
-- 9、yieldstart、yieldreturn、yieldbreak实际上是用lua不对称协程实现对称协同,使用方式和Unity侧协同类似,注意点看相关函数头说明
-- TODO:
-- 1、CS侧做可视化调试器,方便单步查看各个协程运行状态
--]]

-- 协程内部使用定时器实现,定时器是weak表,所以这里必须缓存Action,否则会被GC回收
local action_map = {}
-- action缓存池
local action_pool = {}
-- 用于子级协程yieldreturn时寻找父级协程
local yield_map = {}
-- 协程数据缓存池
local yield_pool = {}
-- 协程缓存池
local co_pool = {}

-- 回收协程
local function __RecycleCoroutine(co)
   if not coroutine.status(co) == "suspended" then
      error("Try to recycle coroutine not suspended : "..coroutine.status(co))
   end
   
   table.insert(co_pool, co)
end

-- 可复用协程
local function __Coroutine(func, ...)
   local args = SafePack(...)
   while func do
      local ret = SafePack(func(SafeUnpack(args)))
      __RecycleCoroutine(coroutine.running())
      args = SafePack(coroutine.yield(SafeUnpack(ret)))
      func = args[1]
      table.remove(args, 1)
   end
end

-- 获取协程
local function __GetCoroutine()
   local co = nil
   if table.length(co_pool) > 0 then
      co = table.remove(co_pool)
   else
      co = coroutine.create(__Coroutine)
   end
   return co
end

-- 回收Action
local function __RecycleAction(action)
   action.co = false
   action.timer = false
   action.func = false
   action.args = false
   action.result = false
   table.insert(action_pool, action)
end

-- 获取Action
local function __GetAction(co, timer, func, args, result)
   local action = nil
   if table.length(action_pool) > 0 then
      action = table.remove(action_pool)
   else
      action = {false, false, false, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值