2016-04-03 7 views
2

Ich habe eine Netzwerkanwendung, die Lua-Skripts verwendet. Nach dem Start der Anwendung erstelle ich einen globalen Lua-Status und lade alle Skriptdateien, die verschiedene Funktionen enthalten. Für jeden Client, der eine Verbindung herstellt, erstelle ich einen Lua-Thread für diese Verbindung.Abbrechen Ertrag von Host

Wenn eine Anfrage, die ein Skript verwendet, kommt, bekomme ich die globale Funktion und rufe sie auf.

var NL = connection.State; 

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

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

Nun verlangen einige Skripte eine Antwort auf etwas, von dem Client, so dass ich Ausbeute in diesen Funktionen, darauf zu warten. Wenn die Antwort eingeht, wird das Skript mit lua_resume(NL, 1) fortgesetzt.

// 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); 
// ... 

Mein Problem ist, dass ich die Ausbeute in der Lage sein müssen und von der Lua-Funktion zurückkehren zu annullieren, ohne dass in der Lua-Funktion mehr Code ausgeführt, und ohne zusätzlichen Code zu den Skripten hinzuzufügen. Mit anderen Worten, ich möchte im Grunde den Lua-Thread eine Ausnahme machen lassen, zurück zum Anfang gehen und vergessen, dass er diese Funktion jemals ausgeführt hat.

Ist das möglich?

Eine Sache, die ich dachte, könnte funktionieren, aber nicht, rief lua_error. Das Ergebnis war ein SEHException auf dem lua_error Aufruf. Ich nehme an, weil das Skript momentan nicht läuft, sondern nachgibt.

Antwort

0

Während ich keinen Weg gefunden habe, den Schiefer eines Threads sauber zu machen (ich glaube nicht, dass es möglich ist), fand ich eine Lösung, um herauszufinden, wie lua_newthread funktioniert.

Wenn der Thread erstellt wird, wird der Verweis darauf auf den Stack des globalen Status gesetzt, und er wird erst gesammelt, wenn er von dort entfernt wird. Alles, was Sie tun müssen, um den Faden zu reinigen, ist, ihn mit lua_remove vom Stapel zu entfernen. Dazu müssen Sie regelmäßig neue Threads erstellen, aber das ist für mich kein großes Problem.

Ich behalte jetzt die erstellten Threads und ihren Index auf dem Stapel, also kann ich sie entfernen, wenn ich mit ihnen aus irgendeinem Grund fertig bin (Abbruch, Fehler, usw.). Alle anderen Indizes werden aktualisiert, da die Entfernung diejenigen verschiebt, die danach kamen.

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

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