Ich hatte neulich ein Gespräch mit meinem Freund. Ich habe gesagt, dass man in reinem Lua kein präemptives Multitasking-System aufbauen kann. Er behauptet, dass Sie das können, aus folgendem Grund:
Sowohl C als auch Lua haben keine eingebauten Threading-Bibliotheken [Anmerkung des OP: Nun, Lua technisch, aber AFAIK ist nicht nützlich für unsere Zwecke]. Windows, das größtenteils in C (++) geschrieben ist, hat präemptives Multitasking, das sie von Grund auf neu erstellten. Daher sollten Sie in der Lage sein, das Gleiche in Lua zu tun. Das große Problem, das ich damit sehe, ist, dass präemptives Multitasking nach meinem Wissen hauptsächlich so funktioniert, dass es regelmäßige Interrupts erzeugt, mit denen der Manager die Kontrolle übernimmt und festlegt, an welchem Code er als nächstes arbeiten soll. Ich denke auch nicht, dass Lua irgendeine Einrichtung hat, die das kann.
Meine Frage ist: ist es möglich, eine Pure-Lua-Bibliothek zu schreiben, die es Menschen ermöglicht, präemptives Multitasking zu haben?
Ich kann nicht sehen, wie es geht, obwohl es ohne eine formale Semantik von Lua (wie die Semantik von yield
zum Beispiel) wirklich schwierig ist, mit eisernen Argumenten zu argumentieren, warum das nicht möglich ist. (Ich habe eine formale Semantik für Zeitalter gesucht, aber Roberto und lhf haben offensichtlich bessere Dinge zu tun.)
Wenn ich vorbeugendes Multitasking für Lua wollte, würde ich nicht einmal versuchen, es in reinem Lua zu machen. Stattdessen würde ich einen alten Trick verwenden, den ich vor 20 Jahren in Standard ML of New Jersey gesehen habe:
Interrupt setzt eine Markierung in lua_State
, die besagt, dass "die aktuelle Coroutine deaktiviert wurde".
Ändern Sie die VM so, dass sie bei jeder Schleife und bei jedem Funktionsaufruf das Flag überprüft und ggf. nachgibt.
Dieser Patch wäre einfach zu schreiben und einfach zu warten. Es löst nicht das Problem der lang laufenden C-Funktion, die nicht vorweggenommen werden kann, aber wenn Sie dieses Problem lösen müssen, wandern Sie in viel härteres Gebiet und Sie können genauso gut Ihr gesamtes Threading erledigen die C-Ebene, nicht die Lua-Ebene.
Nicht, dass ich davon weiß, nein. Es wäre fast schon absurd einfach, wenn man mit Hilfe von debug.sethook von Hooks, die auf Coroutinen gesetzt sind, profitieren könnte, aber es funktioniert nicht. Sie können aus C-Haken ergeben, die aus C (lua_sethook) gesetzt sind, aber ich konnte genau dafür nicht herausfinden, und es ist sowieso kein reines Lua.
Selbst wenn es möglich wäre, wäre es kein echtes Threading. Alles würde immer noch innerhalb desselben Betriebssystem-Threads laufen. Ihr Hook würde eine Vielzahl von Faktoren berücksichtigen (wie Zeit, vielleicht Speicher usw.) und dann bestimmen, ob er nachgibt. Die Coroutine würde dann entscheiden, welche Kindercoroutine als nächstes ausgeführt werden soll. Sie müssen auch entscheiden, wann der Hook aufgerufen werden soll. Am häufigsten würde es bei jedem Lua-Unterricht sein, aber das bringt eine Leistungseinbuße mit sich. Und wenn die Coroutine eine C-Funktion aufruft, hat Lua keine Zuständigkeit. Wenn dieser C-Aufruf lange dauert, können Sie nichts dagegen tun.
Hier ist ein verwandter Thread aus der Lua-L-Mailingliste, der Sie könnten interessant finden.
Nein. Es ist nicht möglich, einen präemptiven Scheduler in reinem Lua zu schreiben. An einem gewissen Punkt benötigt ein präventiver Scheduler einen Mechanismus wie eine Interrupt-Service-Routine, um die Steuerung vom aktuellen Thread wegzunehmen und sie dem Scheduler zu übergeben, der sie dann einem anderen Thread geben kann. Reines Lua hat diesen Mechanismus nicht.
Sie erwähnen, dass Windows hauptsächlich in C / C ++ geschrieben ist. Das Schlüsselwort ist meistens. Sie können einen preemptive Scheduler in reinem ANSI C / C ++ nicht schreiben. Normalerweise wird ein Teil der Interrupt-Service-Routine in Assembler geschrieben. Oder der C / C ++ - Compiler implementiert eine nicht standardmäßige Erweiterung, die es ermöglicht, Interrupt-Service-Routinen in C / C ++ zu schreiben. Einige Compiler ermöglichen es Ihnen, Funktionen mit einem __interrupt-Modifizierer zu deklarieren, der bewirkt, dass der Compiler einen prolong / epilog generiert, der es ermöglicht, die Funktion als Interrupt-Service-Routine zu verwenden.
Auch Code, der die Interrupt-Serviceroutine einrichtet, fidelt mit CPU-Registern mit speicherabgebildetem IO oder einem IO-Befehl. Keiner dieser Code ist portable ANSI C / C ++. Und, hängt von der CPU-Architektur ab.
Tags und Links multithreading lua preemptive