使用 Windows 纤程实现非阻塞 Lua 执行

lua-users home
wiki

作为 非阻塞 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 纤程。

已知问题


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2008 年 3 月 28 日凌晨 1:50 GMT (差异)