使用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协程。

已知问题


RecentChanges · preferences
编辑 · 历史
最后编辑于2008年3月27日晚上8:50 GMT (差异)