暂停 lua 来自外部函数的协程以在调度程序中使用
Pause lua coroutine from outside function for use in a scheduler
这已经在之前讨论过,从外部可以完成的所有事情似乎就是杀死协程。这对于调度程序来说当然是不实用的。有没有办法从外部暂停协程或者可能有解决方法?
从 C API,您可以 set a hook 将在 $n
行/指令后产生。 (这通过 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
change/remove 设置钩子,反之亦然——这会抛出错误或默默地造成混乱。但你可以扩展 setyieldhook
来检测& clear "normal" Lua hooks,and/or wrap debug.sethook
检查并清除 yield hook。)
其他注意事项:
- 如果协程
yield
s,这不会重置挂钩计时器。
- 协程将退出而不返回任何东西,所以你可能想要
包装
coroutine.yield
and/or coroutine.resume
这样你就可以区分了
"normal" yield
s 从超时开始 yield
s.
- C 函数不计算处理的指令数,因此
不会触发钩子(例如 long-运行 非贪婪字符串匹配通过
string.*
),因此这不提供硬时序保证。
这已经在之前讨论过,从外部可以完成的所有事情似乎就是杀死协程。这对于调度程序来说当然是不实用的。有没有办法从外部暂停协程或者可能有解决方法?
从 C API,您可以 set a hook 将在 $n
行/指令后产生。 (这通过 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
change/remove 设置钩子,反之亦然——这会抛出错误或默默地造成混乱。但你可以扩展 setyieldhook
来检测& clear "normal" Lua hooks,and/or wrap debug.sethook
检查并清除 yield hook。)
其他注意事项:
- 如果协程
yield
s,这不会重置挂钩计时器。 - 协程将退出而不返回任何东西,所以你可能想要
包装
coroutine.yield
and/orcoroutine.resume
这样你就可以区分了 "normal"yield
s 从超时开始yield
s. - C 函数不计算处理的指令数,因此
不会触发钩子(例如 long-运行 非贪婪字符串匹配通过
string.*
),因此这不提供硬时序保证。