使用 Windows 纤程实现非阻塞 Lua 执行 |
|
以下示例是一个控制台应用程序,它运行一个 Lua 脚本,但可以通过按任意键随时停止。脚本可以执行任何操作,程序仍然可以处理按键。
Main.cpp
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400 // Necessary to enable fiber functions.
#endif
#include <Windows.h>
#include <conio.h>
extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
LPVOID g_PrimaryFiber = NULL;
LPVOID g_LuaFiber = NULL;
lua_State* pLua = NULL;
VOID CALLBACK LuaFiberProc(PVOID lpParameter)
{
luaL_dofile(pLua, "Script.lua");
}
int main()
{
pLua = luaL_newstate();
luaL_openlibs(pLua);
g_PrimaryFiber = ConvertThreadToFiber(NULL);
g_LuaFiber = CreateFiber(0, LuaFiberProc, NULL);
for (;;)
{
if (_kbhit())
{
printf("This program has successfully used fibers!\n");
printf("Goodbye.\n");
return 0;
}
SwitchToFiber(g_LuaFiber);
}
}
以下是 lvm.c 中显示的更改部分
...
////////////////
// CHANGES HERE
////////////////
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
#include <Windows.h>
extern LPVOID g_PrimaryFiber;
////////////////
////////////////
void luaV_execute (lua_State *L, int nexeccalls) {
LClosure *cl;
StkId base;
TValue *k;
const Instruction *pc;
reentry: /* entry point */
lua_assert(isLua(L->ci));
pc = L->savedpc;
cl = &clvalue(L->ci->func)->l;
base = L->base;
k = cl->p->k;
/* main loop of interpreter */
for (;;) {
////////////////
// CHANGES HERE
////////////////
Instruction i;
StkId ra;
SwitchToFiber(g_PrimaryFiber);
i = *pc++;
////////////////
////////////////
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
...
它的工作原理是在两个纤程中运行程序:主纤程和 Lua 纤程。主纤程是程序的主要部分,Lua 纤程是 Lua 脚本运行的地方。luaV_execute 被修改为在脚本操作之间切换回主纤程,主纤程在完成处理后切换回 Lua 纤程。
已知问题