2016-04-03 53 views
2

我有一個使用Lua腳本的網絡應用程序。在啓動應用程序時,我創建一個全局Lua狀態並加載所有包含各種函數的腳本文件,併爲每個連接的客戶端創建一個Lua線程,以用於該連接。取消主機收益

// On start 
var GL = luaL_newstate(); 
// register functions... 
// load scripts... 

// On connection 
connection.State = lua_newthread(GL); 

當使用腳本的請求進來時,我得到全局函數並調用它。

var NL = connection.State; 

var result = lua_resume(NL, 0); 
if (result != 0 && result != LUA_YIELD) 
{ 
    // error... 
    result = 0; 
} 

if (result == 0) 
{ 
    // function returned... 
} 

現在,一些腳本需要從客戶端響應某些東西,所以我在這些功能中屈服,等待它。當響應進入時,腳本將以lua_resume(NL, 1)恢復。

// Lua 
text("How are you?") 
local response = select("Good", "Bad") 

// Host 
private int select(IntPtr L) 
{ 
    // send response request... 
    return lua_yield(L, 1); 
} 

// On response 
lua_pushstring(NL, response); 
var result = lua_resume(NL, 1); 
// ... 

我的問題是,我需要能夠取消該產量,從Lua中的函數返回,沒有執行在Lua的功能更多的代碼,而無需增加額外的代碼的腳本。換句話說,我基本上想讓Lua線程拋出一個異常,重新開始,並忘記它曾經執行過這個函數。

這可能嗎?

我認爲有一件事可以奏效,但沒有,正在呼籲lua_error。結果是撥打lua_error致電SEHException。我假設,因爲腳本目前沒有運行,但屈服。

回答

0

雖然我沒有找到一種方法來擦拭線程的清潔(我不認爲這是可能的),但我確實找到了解決方案,以確定lua_newthread的工作原理。

創建線程時,其引用被放在「全局」狀態的堆棧上,直到從該處移除後纔會被收集。您需要做的所有清理線程的工作是使用lua_remove將其從堆棧中移除。這需要你定期創建新線程,但這對我來說並不是什麼大問題。

我現在正在跟蹤堆棧中創建的線程和它們的索引,因此無論出於何種原因(取消,錯誤等)完成它們時,都可以將它們刪除。所有其他指數都會更新,因爲移除將會改變之後的指數。

if (sessionOver) 
{ 
    lua_remove(GL, thread.StackIndex); 

    foreach (var t in threads) 
    { 
     if (t.StackIndex > thread.StackIndex) 
      t.StackIndex--; 
    } 
}