多线程串行运行 Lua 虚拟机

1,883次阅读
没有评论

ltask 是一个功能类似 skynet 的库。我主要将它用于客户端环境。由于比 skynet 后设计,所以我在它上面实验了许多新想法。

最近碰到一个需求:我们的游戏引擎中嵌入的第三方 C++/C++ 模块以 callback 形式提供了若干接口。在把这些模块嵌入 ltask 的服务中运行时,这些 callback 函数是难以使用全部 ltask 的特性。比如,我们的 IO 操作全部在一个独立服务中,引擎读取文件时,很可能是通过网络异步远程加载数据的。这些第三方模块通常没有考虑异步 IO 操作,都是以同步 IO 方式给出一个读文件的 callback 函数让使用者填写。

那么,怎样才能在这个 C callback 中挂起当前任务,等待 IO 的异步完成呢?

初看是不可能做到的。框架没有设计成支持异步机制,我们难以从 C 函数中 yield ,挂起当前任务。这样,同一个服务就不可能在 callback 结束前相应外部消息,也就无法利用 ltask 的调度器完成异步 IO 工作。

Lua 虚拟机也并没有(也无必要)设计成多线程安全的,我们不能把这个 C 模块及其 Lua binding 的运行环境放在一个独立线程环境中。所以,callback 中阻塞调用 IO 请求,就意味着整个服务的阻塞。

一个比较简单的解决方法是给 IO 服务额外开通一个 channel ,不走 ltask 内部的消息。在 C callback 中,通过这个额外的 channel 和 IO 服务通讯。

但我仔细思考了这个问题,发现当 C callback 不返回时,未必整个服务必须跟着一起阻塞住。其实,只要 ltask 框架稍做一些支持,我们还是可以让服务继续工作的。

现在的任务调度模型是:由调度器分配一个工作线程运行一个服务的一小段任务(通常是用 lua resume 运行 lua vm 中的一个 coroutine 一个片段),在此期间,服务处于忙状态,别的工作线程无法拿到该服务。这就保证了单个服务不会重入。

当这一段任务执行完毕,而服务的消息队列为空时,调度器将服务设为闲置状态。等有新的消息投递到服务的消息队列后,闲置状态的服务会重新回到调度器中。

如果我们给服务一个新的状态:在 C 函数中挂起。那么,其实我们还是可以让服务重新进入调度器。从 ltask 的调度器视角来看,它冻结了一整个工作线程,但服务内的 Lua 虚拟机其实也处于停滞状态(因为停在了 C Side ),只要它不回到 Lua side ,这个 Lua 虚拟机依旧可以工作。调度器所作的工作只是把服务的忙状态取消即可。这样,其它工作线程就可以正常的调度它了。

但框架还需要多做一些工作。因为 Lua VM 的工作 coroutine 也处于忙状态,我们不能继续在这个 coroutine 在运行新的代码。所以在此时,应该在该 Lua VM 中创建出一个新的 coroutine 并取代服务的工作 coroutine 。然后让 C callback 等待到一个操作系统的条件变量上;直到业务层认为事情已经完成,需要回到一开始挂起的 C Callback 时,再将环境恢复,唤醒操作系统的条件变量,交还执行流。

在这个流程中,服务中的 Lua VM 从未处于并行状态,所以是安全的。但稍显怪异的是,Lua VM 的确工作在多线程环境下,由两个不同的操作系统线程在独立运行不同的 Lua coroutine 。这样,才保证了其中一个 Lua coroutine 可以一直保有自己的 C 调用栈。

这种运行 Lua VM 的方式,我称之为多线程串行运行。需要注意一些原本在 Lua 中成立的约束不成立了。比如,在单线程环境下,如果你运行一个 Lua 函数,该函数没有修改一个全局状态,函数也没有让出,那么可以认为这个全局状态是不会改变的;但现在,这个函数可能在 C side 挂起,而另一个操作系统线程可能从另外一个 lua coroutine 修改这个状态。

在我们的初步实践中发现,对应的 C/C++ 模块最好也能设计成多线程安全的。虽然在这个模型下,C 代码也没有并行的问题,但会多出很多重入问题。即,一个 C 函数运行了一半,有可能挂起,由另外一个系统线程再进入一次。一般非线程安全的 C 模块很可能在这方面考虑不周。(接口中有 callback 的框架更容易出现重入 bug )

我在 ltask 的 taskrun 分支实现了这个特性

ltask 是一个功能类似 skynet 的库。我主要将它用于客户端环境。由于比 skynet 后设计,所以我在它上面实验了许多新想法。

最近碰到一个需求:我们的游戏引擎中嵌入的第三方 C/C++ 模块以 callback 形式提供了若干接口。在把这些模块嵌入 ltask 的服务中运行时,这些 callback 函数是难以使用全部 ltask 的特性。比如,我们的 IO 操作全部在一个独立服务中,引擎读取文件时,很可能是通过网络异步远程加载数据的。这些第三方模块通常没有考虑异步 IO 操作,都是以同步 IO 方式给出一个读文件的 callback 函数让使用者填写。

那么,怎样才能在这个 C callback 中挂起当前任务,等待 IO 的异步完成呢?

初看是不可能做到的。框架没有设计成支持异步机制,我们难以从 C 函数中 yield ,挂起当前任务。这样,同一个服务就不可能在 callback 结束前相应外部消息,也就无法利用 ltask 的调度器完成异步 IO 工作。

Lua 虚拟机也并没有(也无必要)设计成多线程安全的,我们不能把这个 C 模块及其 Lua binding 的运行环境放在一个独立线程环境中。所以,callback 中阻塞调用 IO 请求,就意味着整个服务的阻塞。

一个比较简单的解决方法是给 IO 服务额外开通一个 channel ,不走 ltask 内部的消息。在 C callback 中,通过这个额外的 channel 和 IO 服务通讯。

但我仔细思考了这个问题,发现当 C callback 不返回时,未必整个服务必须跟着一起阻塞住。其实,只要 ltask 框架稍做一些支持,我们还是可以让服务继续工作的。

现在的任务调度模型是:由调度器分配一个工作线程运行一个服务的一小段任务(通常是用 lua resume 运行 lua vm 中的一个 coroutine 一个片段),在此期间,服务处于忙状态,别的工作线程无法拿到该服务。这就保证了单个服务不会重入。

当这一段任务执行完毕,而服务的消息队列为空时,调度器将服务设为闲置状态。等有新的消息投递到服务的消息队列后,闲置状态的服务会重新回到调度器中。

如果我们给服务一个新的状态:在 C 函数中挂起。那么,其实我们还是可以让服务重新进入调度器。从 ltask 的调度器视角来看,它冻结了一整个工作线程,但服务内的 Lua 虚拟机其实也处于停滞状态(因为停在了 C Side ),只要它不回到 Lua side ,这个 Lua 虚拟机依旧可以工作。调度器所作的工作只是把服务的忙状态取消即可。这样,其它工作线程就可以正常的调度它了。

但框架还需要多做一些工作。因为 Lua VM 的工作 coroutine 也处于忙状态,我们不能继续在这个 coroutine 在运行新的代码。所以在此时,应该在该 Lua VM 中创建出一个新的 coroutine 并取代服务的工作 coroutine 。然后让 C callback 等待到一个操作系统的条件变量上;直到业务层认为事情已经完成,需要回到一开始挂起的 C Callback 时,再将环境恢复,唤醒操作系统的条件变量,交还执行流。

在这个流程中,服务中的 Lua VM 从未处于并行状态,所以是安全的。但稍显怪异的是,Lua VM 的确工作在多线程环境下,由两个不同的操作系统线程在独立运行不同的 Lua coroutine 。这样,才保证了其中一个 Lua coroutine 可以一直保有自己的 C 调用栈。

这种运行 Lua VM 的方式,我称之为多线程串行运行。需要注意一些原本在 Lua 中成立的约束不成立了。比如,在单线程环境下,如果你运行一个 Lua 函数,该函数没有修改一个全局状态,函数也没有让出,那么可以认为这个全局状态是不会改变的;但现在,这个函数可能在 C side 挂起,而另一个操作系统线程可能从另外一个 lua coroutine 修改这个状态。

在我们的初步实践中发现,对应的 C/C++ 模块最好也能设计成多线程安全的。虽然在这个模型下,C 代码也没有并行的问题,但会多出很多重入问题。即,一个 C 函数运行了一半,有可能挂起,由另外一个系统线程再进入一次。一般非线程安全的 C 模块很可能在这方面考虑不周。(接口中有 callback 的框架更容易出现重入 bug )

我在 ltask 的 taskrun 分支实现了这个特性

 

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)

文心AIGC

2023 年 3 月
 12345
6789101112
13141516171819
20212223242526
2728293031  
文心AIGC
文心AIGC
人工智能ChatGPT,AIGC指利用人工智能技术来生成内容,其中包括文字、语音、代码、图像、视频、机器人动作等等。被认为是继PGC、UGC之后的新型内容创作方式。AIGC作为元宇宙的新方向,近几年迭代速度呈现指数级爆发,谷歌、Meta、百度等平台型巨头持续布局
文章搜索
热门文章
潞晨尤洋:日常办公没必要上私有模型,这三类企业才需要 | MEET2026

潞晨尤洋:日常办公没必要上私有模型,这三类企业才需要 | MEET2026

潞晨尤洋:日常办公没必要上私有模型,这三类企业才需要 | MEET2026 Jay 2025-12-22 09...
面向「空天具身智能」,北航团队提出星座规划新基准丨NeurIPS’25

面向「空天具身智能」,北航团队提出星座规划新基准丨NeurIPS’25

面向「空天具身智能」,北航团队提出星座规划新基准丨NeurIPS’25 鹭羽 2025-12-13 22:37...
商汤Seko2.0重磅发布,合作短剧登顶抖音AI短剧榜No.1

商汤Seko2.0重磅发布,合作短剧登顶抖音AI短剧榜No.1

商汤Seko2.0重磅发布,合作短剧登顶抖音AI短剧榜No.1 十三 2025-12-15 14:13:14 ...
跳过“逐字生成”!蚂蚁集团赵俊博:扩散模型让我们能直接修改Token | MEET2026

跳过“逐字生成”!蚂蚁集团赵俊博:扩散模型让我们能直接修改Token | MEET2026

跳过“逐字生成”!蚂蚁集团赵俊博:扩散模型让我们能直接修改Token | MEET2026 一水 2025-1...
10亿美元OpenAI股权兑换迪士尼版权!米老鼠救Sora来了

10亿美元OpenAI股权兑换迪士尼版权!米老鼠救Sora来了

10亿美元OpenAI股权兑换迪士尼版权!米老鼠救Sora来了 一水 2025-12-12 13:56:19 ...
最新评论
ufabet ufabet มีเกมให้เลือกเล่นมากมาย: เกมเดิมพันหลากหลาย ครบทุกค่ายดัง
tornado crypto mixer tornado crypto mixer Discover the power of privacy with TornadoCash! Learn how this decentralized mixer ensures your transactions remain confidential.
ดูบอลสด ดูบอลสด Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.
ดูบอลสด ดูบอลสด Pretty! This has been a really wonderful post. Many thanks for providing these details.
ดูบอลสด ดูบอลสด Pretty! This has been a really wonderful post. Many thanks for providing these details.
ดูบอลสด ดูบอลสด Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
Obrazy Sztuka Nowoczesna Obrazy Sztuka Nowoczesna Thank you for this wonderful contribution to the topic. Your ability to explain complex ideas simply is admirable.
ufabet ufabet Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
ufabet ufabet You’re so awesome! I don’t believe I have read a single thing like that before. So great to find someone with some original thoughts on this topic. Really.. thank you for starting this up. This website is something that is needed on the internet, someone with a little originality!
ufabet ufabet Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.
热评文章
跳过“逐字生成”!蚂蚁集团赵俊博:扩散模型让我们能直接修改Token | MEET2026

跳过“逐字生成”!蚂蚁集团赵俊博:扩散模型让我们能直接修改Token | MEET2026

跳过“逐字生成”!蚂蚁集团赵俊博:扩散模型让我们能直接修改Token | MEET2026 一水 2025-1...
10亿美元OpenAI股权兑换迪士尼版权!米老鼠救Sora来了

10亿美元OpenAI股权兑换迪士尼版权!米老鼠救Sora来了

10亿美元OpenAI股权兑换迪士尼版权!米老鼠救Sora来了 一水 2025-12-12 13:56:19 ...
IDC MarketScape: 容联云位居“中国AI赋能的联络中心”领导者类别

IDC MarketScape: 容联云位居“中国AI赋能的联络中心”领导者类别

IDC MarketScape: 容联云位居“中国AI赋能的联络中心”领导者类别 量子位的朋友们 2025-1...