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

时间:2016-11-18 17:20:57

标签: c multithreading lua coroutine 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协程?

1 个答案:

答案 0 :(得分:3)

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

例如,如果你有Lua函数a调用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中有以下段落:

  

完全可恢复的VM

     

LuaJIT VM完全可以恢复。这意味着即使跨越上下文,您也可以从协同程序中获取,而标准的Lua 5.1 VM无法实现这一点:例如:你可以在整个迭代器和跨方法中跨越pcall()和xpcall()。

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

请注意,使用FFI加载的普通C函数不允许触及Lua状态 at all 。这包括试图屈服。