你可以从C的任何地方收获和恢复Luajit协同程序吗?

我试图想出一个解决方案,从C函数中产生一个Luajit协程,它立即创建一个要在另一个OS线程上处理的tasklet.

根据Lua的各种文件,事情开始相互矛盾,这是不是完全有可能?文件不是很清楚,也没有解释推理.

Lua 5.1声明每个协程都有一个堆栈.但是,只有一个全局C堆栈.我不完全确定为什么这是一个障碍.

Lua 5.2显然用lua_pcallk和lua_yieldk修复了这个问题.但这些解释非常令人困惑.

但是这些都没有说明我正在使用的VM ……这是LuaJIT 2.0.4和LuaJIT 2.1.0.

谷歌搜索告诉我,Luajit 1.x已经实现了CoCo,显然每个lua线程(协同程序)都使用了真正的C堆栈.这允许从任何地方屈服.

只有一个搜索引导我看到显然LuaJIT 2.x没有实现coco,因为每个协程都使用C堆栈.

谁能告诉我从C产生协同程序的问题是什么?并验证我是否可以安全地从c产生/恢复luajit 2.x协同程序?

最佳答案
在引用Lua实现中,每个Lua协程都有自己的Lua堆栈,它只是lua_State内部的一个数组,与C堆栈无关. Lua无法保存C堆栈(因为这在标准C中是不可能的),因此如果当前正在执行C函数,则无法生成协程.

例如,如果你有Lua函数一个调用C函数b调用Lua函数c,并且c试图屈服,Lua将无法保存b的局部变量(因为它是一个C函数)并且将失败.

这也适用于很多内置的Lua函数.正如你所提到的,在Lua 5.1中,实现不支持在pcall上产生,直到Lua 5.2显然添加了特殊功能才能使它工作.

Coco是标准Lua实现的补丁,它在协同程序中实现单独的C堆栈,因此Lua现在可以“保存”C函数变量.显然LuaJit 1.x也包括它.它不适用于LuaJit 2.x,因为它是一个完全不同的Lua实现.

LuaJit 2.x在Extensions page中有以下段落:

Fully Resumable VM

The LuaJIT VM is fully resumable. This means you can yield from a coroutine even across contexts, where this would not possible with the standard Lua 5.1 VM: e.g. you can yield across pcall() and xpcall(), across iterators and across metamethods.

因此,显然可以使用内置函数,但如果它适用于任意Lua C API函数,它仍然是模糊的.但是很容易测试;编写一个简单的C API函数,它接受一个Lua函数并调用它,然后传递一个产生的函数.如果它不起作用,它应该抛出一个错误.

请注意,加载FFI的普通C函数根本不允许触及Lua状态.这包括试图屈服.

转载注明原文:你可以从C的任何地方收获和恢复Luajit协同程序吗? - 代码日志