Non Blocking Lua Execution With Windows Fibers |
|
The example below is a console application which runs a Lua script but can be stopped anytime by pressing a key. The script can do whatever it wants and the program will still process keystrokes.
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); } }
Here's a section of lvm.c showing the change to be made:
... //////////////// // 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)) { ...
It works by running the program in two fibers: the primary fiber and the Lua fiber. The primary fiber is the main part of the program, and the Lua fiber is where the Lua script runs. luaV_execute is changed to switch back to the primary fiber between script operations, and the primary fiber switches back to the Lua fiber when it's done with its processing.
Known issues: