使用 Windows Fibers 進行非封鎖式 Lua 執行

lua-users home
wiki

成為 NonBlockingLuaExecution 功能建議的一部份。

以下範例是一個主控台應用程式,執行一個 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。

已知的問題


RecentChanges · 偏好設定
編輯 · 歷史記錄
最後編輯時間為 2008 年 3 月 28 日上午 1:50 (GMT) (diff)