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传递给yield
    end)
    return coroutine.yield() -- 1. 主动放弃运行,本协程被切换出去
end

使用例子:

---通过顺序编写代码解决回调函数造成同块逻辑被撕裂的例子
---@param _co thread @协程对象
function test(_co)
    for i = 1, 10, 1 do
        local 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 do
        local 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 then
        invoke_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_wrap
    coroutine_resume(cowrap, cowrap) -- 初创建的协程是暂停的,手动触发执行
end

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

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

相关推荐

  1. Lua 模拟 Golang go defer 编程模式

    2024-05-12 09:12:08       12 阅读
  2. 使用 Lua 模拟 Golang go defer 编程模式

    2024-05-12 09:12:08       14 阅读
  3. Lua-coroutine

    2024-05-12 09:12:08       35 阅读
  4. Lua

    2024-05-12 09:12:08       12 阅读
  5. golang 题目

    2024-05-12 09:12:08       14 阅读
  6. Golang并发编程-goroutine初体验

    2024-05-12 09:12:08       12 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-05-12 09:12:08       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-12 09:12:08       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-12 09:12:08       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-12 09:12:08       20 阅读

热门阅读

  1. 您真的会高效使用 Mac 吗?

    2024-05-12 09:12:08       9 阅读
  2. git 命令 - rebase

    2024-05-12 09:12:08       9 阅读
  3. leetcode234-Palindrome Linked List

    2024-05-12 09:12:08       11 阅读
  4. 【C++】list的使用

    2024-05-12 09:12:08       11 阅读
  5. C语言星号带括号的情形

    2024-05-12 09:12:08       10 阅读
  6. 树(Tree)和二叉树

    2024-05-12 09:12:08       10 阅读
  7. Qt中正则表达式的用法

    2024-05-12 09:12:08       11 阅读
  8. Python 正则表达式 (?=...) 和 (?<=...) 符号

    2024-05-12 09:12:08       10 阅读
  9. Electron axios token失效刷新token

    2024-05-12 09:12:08       12 阅读
  10. 2024-05-11 问AI:在深度学习中,学习率是什么

    2024-05-12 09:12:08       11 阅读
  11. Python 实战之量化交易

    2024-05-12 09:12:08       13 阅读
  12. CentOS常见命令

    2024-05-12 09:12:08       7 阅读