使用 Windows Fibers 進行非封鎖式 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)) { ...
它透過執行兩個 fibers 中的程式來進行:主要 fibers 和 Lua fibers。主要 fibers 就是程式的主要部份,而 Lua fibers 是 Lua 腳本執行的部份。luaV_execute 被變更為在腳本操作之間切換回主要 fibers,而主要 fibers 在處理完畢後會再切換回 Lua fibers。
已知的問題