从外部函数暂停lua协程以在调度程序中使用

时间:2017-07-02 14:07:24

标签: lua coroutine

之前已经讨论过,所有可以从外部完成的事情似乎都是杀死了协程。这对于调度程序当然不实用。有没有办法暂时从外部暂停协同程序或者可能是解决方法?

1 个答案:

答案 0 :(得分:0)

在C API中,您可以在$n行/说明之后产生set a hook。 (这不可能通过debug.sethook,因为它会添加一个阻止其工作的中间层。)

你可以把它包装成一个你可以暴露给Lua的单个函数,所以除了添加那个函数之外,你可以从Lua中完成。例如:

static int setyieldhook( lua_State * L ) {
   lua_State * coro;
   int steps;
   luaL_checktype( L, 1, LUA_TTHREAD );
   coro = lua_tothread( L, 1 );
   steps = luaL_optinteger( L, 2, 0 );
   if (steps <= 0) {
      lua_sethook( coro, NULL, 0, 0 );
   } else {
      lua_sethook( coro, yieldhook, LUA_MASKCOUNT, steps );
   }
   return 0;
}

然后将其作为函数推送到Lua并为其命名,例如debug.setyieldhook

这个将用作debug.setyieldhook( coro, timeout ),每当协程运行时,它将在timeout Lua指令后产生。要清除debug.setyieldhook( coro, 0 )。 (注意:您无法更改/删除通过setyieldhook通过debug.sethook设置的挂钩,反之亦然 - 这会抛出错误或无声地造成混乱。但您可以将setyieldhook扩展为检测&amp;清除&#34;正常&#34; Lua钩子,和/或包裹debug.sethook以检查&amp;清除yield钩子。)

需要注意的其他事项:

  • 如果是协程yield,则不会重置挂钩计时器。
  • 协程会在没有返回任何内容的情况下产生,所以你可能想要 包裹coroutine.yield和/或coroutine.resume,以便分开 &#34;正常&#34; yield来自超时yield s。
  • C函数不会计算处理的指令数,等等 不会触发挂钩(例如,长时间运行的非贪婪字符串匹配 string.*),所以这并不能提供硬时间保证。