当前位置: 首页 > news >正文

Lua 协程模拟 Golang 的 go defer 编程模式

封装go函数用于创建并启动一个协程:

---go函数创建并启动一个协程
---@param _co_task function @函数原型 fun(_co:thread)
function go(_co_task)local co = coroutine.create(_co_task) -- 创建一个暂停的协程coroutine.resume(co, co) -- 调用coroutine.resume激活协程执行
end

封装项目中的异步函数用于成为协程函数:

---封装c_model.c_foo异步函数,成为协程函数
---@param _co thread @协程对象
---@return boolean,string
function co_foo(_co)c_model.c_foo(function(_ok, _result)coroutine.resume(_co, _ok, _result) -- 2. 回调函数被调用后,激活本协程继续执行,并把_ok和_result传递给yieldend)return coroutine.yield() -- 1. 主动放弃运行,本协程被切换出去
end

使用例子:

---通过顺序编写代码解决回调函数造成同块逻辑被撕裂的例子
---@param _co thread @协程对象
function test(_co)for i = 1, 10, 1 dolocal ok, result = co_foo(_co) -- co_foo函数会先yield切出,等内部回调被执行时再通过resume重新切回来继续执行print(ok, result)end
end-- 启动test协程
go(test)

封装defer用于处理协程的正常和异常退出:

首先定义defer函数,让它具备能够多次被调用的能力:

function defer(_co_wrap, h)table.insert(_co_wrap.defer_handlers, h)
end

同时定义co_error对象用于判断是否有错误:

---@class co_error
---@field ok boolean

定义invoke_defer_handlers函数来执行defer操作:

function invoke_defer_handlers(_co_wrap, _co_error)for i=#_co_wrap.defer_handlers, 1, -1 dolocal h = _co_wrap.defer_handlers[i]xpcall(h, function(err) print(err) end, _co_error)end
end

定义coroutine_resume函数来处理协程的异常退出:

function coroutine_resume(_co_wrap, ...)local ok, errmsg = coroutine.resume(_co_wrap.co, ...)if not ok theninvoke_defer_handlers(_co_wrap, {ok=false}) -- 异常退出end
end

定义go函数来处理协程的正常退出:

function go(_co_task)local co = coroutine.create(function(_co_wrap)_co_task(_co_wrap)invoke_defer_handlers(_co_wrap, {ok=true}) -- 正常退出end)local cowrap = { co = co, defer_handlers = {} } ---@type co_wrapcoroutine_resume(cowrap, cowrap) -- 初创建的协程是暂停的,手动触发执行
end

通过以上封装,可以在Lua中以类似Golang的方式编写协程代码。

协程间的通信暂时不需要在多线程中实现,因为项目中目前只有一个lua_state对象管理。

http://www.lryc.cn/news/346180.html

相关文章:

  • maven的安装与配置(超详细)
  • springCloud服务降级使用到的组件
  • Spring框架学习-详细
  • fatal: fetch-pack: invalid index-pack output
  • 相机购买指南
  • STM32微秒级别延时--F407--TIM1
  • AI图书推荐:杀手级ChatGPT提示词——利用人工智能实现成功与盈利
  • AI时代:低代码与人工智能引领科技创造新时代
  • 1.基于python的单细胞数据预处理-降维可视化
  • 【快捷部署】023_HBase(2.3.6)
  • Nginx配置项详解
  • 解决iview(view ui)中tabs组件中使用图片预览组件ImagePreview,图片不显示问题
  • R2S+ZeroTier+Trilium
  • 10 华三vlan技术介绍
  • 实现一个聊天室可发送消息语音图片视频表情包(任意文件)
  • 【SpringMVC 】什么是SpringMVC(一)?如何创建一个简单的springMvc应用?
  • 【配置】IT-Tools部署
  • 【Python】如何训练模型并保存本地和加载模型
  • 浅谈如何利用 AI 提高内容生产效率?|TodayAI
  • 毕业论文答辩PPT怎么做?推荐3个ai工具帮你一键生成答辩ppt
  • 力扣 5-11
  • redisson 使用脚本实现判断元素不在队列中则插入的原子操作
  • LLaMA详细解读
  • 纯血鸿蒙APP实战开发——页面间共享组件实例的案例
  • 华为机考入门python3--(22)牛客22- 汽水瓶
  • Xilinx 千兆以太网TEMAC IP核简介
  • 激光测径仪在胶管生产中扮演着什么角色?
  • 数据结构与算法===递归
  • 面试官:BIO、NIO 和 AIO 有什么区别?
  • HTML:元素属性详解及代码示例