Threadverzögerung und Tastaturereignisse in OCaml

8

Hier ist eine einfache Spielschleife in OCaml. Der Status wird angezeigt, die Eingabe wird empfangen und der Status wird erweitert. Die Anzahl der Bilder pro Sekunde wird auf 40 beschränkt, indem der Thread für 0,025 Sekunden pro Schleife verzögert wird.

main.ml:

%Vor%

In diesem Beispiel gibt die Funktion get_input einfach Tastenanschläge an das Fenster aus.

input.ml:

%Vor%

Makefile für einfaches Testen:

%Vor%

Dies funktioniert größtenteils, aber wenn Tasten sehr schnell gedrückt werden, stürzt das Programm mit diesem Fehler ab:

Fatal error: exception Unix.Unix_error(2, "select", "")

Ich glaube, es hat etwas mit Thread.delay zu tun. Was verursacht dieses Problem und was ist der beste Weg, um eine konstante FPS zu erreichen?

    
Matthew Piziak 29.05.2012, 22:10
quelle

1 Antwort

9

Ich bin mir nicht ganz sicher, was passiert (es hängt von der Implementierung von Thread.delay ab, die ich nicht kenne). Fehler 2 ist jedoch Unix.EAGAIN , was einen vorübergehenden Mangel an Kernel-Ressourcen darstellt. Wie der Name schon sagt, solltest du wahrscheinlich einfach versuchen, dein Thread.delay erneut zu machen. Wenn ich try ... with verwende, um die Unix.Unix_error-Ausnahme abzufangen, sehe ich keine anderen Fehler außer EAGAIN. Wenn ich nur eine Nachricht drucke und fortfahre, scheint das Programm zu funktionieren. Zumindest gibt es weiterhin Zeichen im Fenster und stürzt nicht ab. Ich arbeite in OS X 10.7 (Lion). Es könnte für Sie anders funktionieren.

Bearbeiten

Ein weiteres mögliches Problem mit diesem Code ist, dass Sys.time() die Prozessor -Zeit zurückgibt, die nur zunimmt, während der Prozess eine echte Berechnung durchführt. Es erhöht sich nicht, während der Prozess auf Eingabe wartet. Dies bedeutet, dass die Verzögerung immer aufgerufen wird, auch wenn Sie lange Zeit zwischen den Tastendrücken warten (das verwirrte mich eine Weile). Es könnte besser sein, Unix.gettimeofday () zu verwenden, was die Wanduhrzeit zurückgibt.

Bearbeiten 2

Nach einigen weiteren Nachforschungen und Tests glaube ich, dass der Unix.EAGAIN -Fehler Ihnen sagt, dass die volle Verzögerung durch ein Ereignis unterbrochen wurde. In deinem Fall ist das unterbrechende Ereignis die Ankunft eines Charakters (glaube ich). Wenn Sie also die ganze Zeit warten möchten, sollten Sie den einzelnen Aufruf von Thread.delay() durch eine Schleife ersetzen.

Damit erhalten Sie für Ihren Hauptcode etwa Folgendes:

%Vor%

(Wenn Sie Unix.select verwenden, um Ihre Verzögerung zu verzögern, können Sie die Abhängigkeit von Threads entfernen. Sie benötigen sie jedoch aus anderen Gründen. Der Code sieht genauso aus, außer der Fehler ist EINTR anstatt EAGAIN.)

    
Jeffrey Scofield 30.05.2012, 01:33
quelle