2017-07-02 151 views

回答

1

從C API,你可以set a hook,這將產生$n線/指令後。 (這是不可能通過debug.sethook,因爲它增加了一箇中間層,防止它的工作。)

你可以把它包裝成一個可以暴露給Lua的函數,所以除了添加那個功能,你可以從Lua做到。例如:

static int setyieldhook(lua_State * L) { 
    lua_State * coro; 
    int steps; 
    luaL_checktype(L, 1, LUA_TTHREAD); 
    coro = lua_tothread(L, 1); 
    steps = luaL_optinteger(L, 2, 0); 
    if (steps <= 0) { 
     lua_sethook(coro, NULL, 0, 0); 
    } else { 
     lua_sethook(coro, yieldhook, LUA_MASKCOUNT, steps); 
    } 
    return 0; 
} 

然後只是將它作爲函數推送給Lua併爲其命名,例如, debug.setyieldhook

這一個將用作debug.setyieldhook(coro, timeout)並且只要協程運行,它將在timeout之後產生Lua指令。要清除,debug.setyieldhook(coro, 0)。 (注:不能更改/通過debug.sethook,反之亦然刪除通過setyieldhook設置掛鉤 - 這將拋出一個錯誤,或者靜靜地創建一個爛攤子,但你可以擴展setyieldhook檢測&明確的「正常」的Lua掛鉤,和/或包裝debug.sethook來。檢查&清除產量掛鉤)

其他的事情需要提防:

  • 如果協程yield S,這不會復位定時器掛鉤。
  • 協程將產生不返回任何東西,所以你可能要 包裝coroutine.yield和/或coroutine.resume這樣你就可以從超時分辨 「正常」 yield小號yield秒。
  • C函數不會計算處理的指令數量,所以 不會觸發掛鉤(例如,長期運行的非貪婪字符串匹配通過 string.*),所以這不提供硬定時保證。
+0

這是一個可行的選項,我可以使用,但很快的問題是,有沒有在標準lua中可以使用的任何實現?也許在某些代碼行間隔插入coroutine.yield()到執行函數中?對我來說,爲我的環境設置C有點不方便,但如果不存在,我將使用上面的選項 – Varscott11

+1

@ Varscott11嗯,可以包裝庫函數以遞增內部(共享)計數器並偶爾產出'。 (所以你基本上是在模擬一個操作系統,比方說,所有'io','os',... functions_can_如果時間到了,就會產生。)或者可能(沒有試過這個)設置一個正常的鉤子任意超時條件,它只用'__index' /'__newindex'替代全局環境或一些經常訪問的事物。當metamethod觸發時,它將它改回到正常的東西,yield,然後(繼續之後)重新對正常的東西進行劫持操作。 – nobody

+0

@ Varscott11(但是這些都是蠻幹的,並不是你想要的,它可以用來進行快速測試等等,但是有很多潛在的奇怪的相互作用和難以測試的破損。如果你想在圖書館使用它/通過C提供給其他人/ ...) – nobody