JNI, DLL, Instanzen
-
Hallo,
da ich für eine Simulation einen sehr genauen Timer benötige, schreibe ich mir diesen in einer DLL, die ich über die JNI anspreche. Das geht auch ganz gut.Im Moment ist das eine DLL mit einer Funktion, die so lange verzögert wird, bis der korrekte Zeitwert verstrichen ist und dann true zurückgibt (wenn kein Fehler aufgetreten ist).
Momentan haben zwei Java-Klassen des Programms so eine DLL, und es werden noch mehr werden. Daher soll eine neue Warten-Klasse dazukommen, die dann nur einmal eine DLL bekommt, welche die bisherigen ersetzt.
Jede Java-Funktion die warten muss erzeugt sich ein Objekt der warten-Klasse und ruft über dieses die Wartenfunktion auf. Diese greift über das JNI auf die neue DLL zu. In dieser DLL will ich eine Klasse schreiben, die eine Warten-Methode hat. Damit bekommt jede Java-Funktion ein eigenes Warten-Objekt in der C++-DLL. Allerdings wird immer dieselbe C++ Funktion aufgerufen, und durch mehrere Threads kann es passieren dass die Funktion mehrmals zeitgleich abläuft.
Macht das Probleme? Oder kann ich das so realisieren?
Dankeschön im Voraus,
exr
-
1. Mich würde der C++-Code interessieren, mit dem du wartest. Zeig den doch mal!
2. Wie genau muss dein Timer sein?
-
Die bisherigen DLLs arbeiten mit QueryPerformanceFrequency und QueryPerformanceCounter.
Der Timer löst bis zu 2us auf.
-
Sieht das ungefähr so aus?
solange_Zeit_nicht_erreicht_ist_mache
{
}
-
In etwa, ja.
Bislang mache ich das so:LARGE_INTEGER Start, Stop, CalVal; QueryPerformanceFrequency(&CalVal); QueryPerformanceCounter(&Start); QueryPerformanceCounter(&Stop); while((( (((jdouble)Stop.QuadPart)-((jdouble)Start.QuadPart)) /((jdouble)CalVal.QuadPart) *1000)+0.5)<MilliSeconds) { MyProcessMessages(); QueryPerformanceCounter(&Stop); }
Diese Funktion soll nun innerhalb der DLL in eine Klasse. Die Warten-Funktion erzeugt dann jedesmal wenn sie aufgerufen wird ein neues Objekt der Klasse und dieses at eigene Variablen (StartZeit, CalVal, Current), damit es da keine Probleme gibt. Frage ist nur, ob das System damit zuercht kommt dass dieselbe Funktion mehrmals gleichzeitig aufgerufen wird.
Die Auflösug von 2us geht übrigens wirklich. Allerdings ist das abhängig von der Geschwindigkeit des CPU-Taktes.
exr
-
exr schrieb:
Die Auflösug von 2us geht übrigens wirklich. Allerdings ist das abhängig von der Geschwindigkeit des CPU-Taktes.
1. Ok, welche Javaversion nutzt du? Ab Java 5.0 (von dem man sich momentan allerdings nur die Beta 2 Version runterladen kann) gibt es die Methode System.nanoTime(), die dir die gleiche Genauigkeit bieten kann. Wenn du 5.0 nutzt, dann würde ich an deiner Stelle also nicht auf JNI ausweichen. In Java 1.4 gibt es so eine Methode AFAIK auch, allerdings nur in den undokumentierten Sun-Klassen.
2. Wenn ich das richtig gesehen habe, dann blockiert deine Anwendung durch das Warten komplett. Sowas halte ich nicht für eine sehr gute Lösung. ...allerdings ist mir klar, dass man, wenn man nicht blockieren will, auf einen normalen Timer ausweichen muss, der eine viel gröbere Genauigkeit bietet (liegt AFAIK so bei 10ms). Wenn das ausreichen würde, würde ich in jedem Fall darauf ausweichen.
-
Hallo,
ich benutze Java 1.4.2_05.
Die Java-Timer sind alle recht unpräzise. Deren Auflösung liegt bei Windows-bsierten 16ms. Im Endeeffekt muss ich 10ms warten können, nur habe ich noch keine FUnktion gefunden die das zuverlässig macht.Die Funktion MyProcessMessages wird immer wieder aufgerufen. Die geht alle Nachrichten durch und sollte in etwa dem ProcessMessages von Borland entsprechen.
Blockeiren finde ich sonst auch nicht so gut, aber ich muss mich darauf verlassen können dass die Funktion nach 10ms wieder anläuft. Meine bisherigen Experimente mit anderen Timern haben eine sehr niedrige Zuverlässigkeit offenbart. Da wurden gerne mal 15 bis 20 daraus.
Der Timer wird übrigens dazu eingesetzt um in Java3D ein Behavior anzustossen (über postID). Da es hierbei schon zu Verzögerungen kommen kann, will ich alle weiteren Unsicherheitsfaktoren beseiteigen.
Welchen Timer würdest du in 1.4.2 vorschlagen?
exr
-
exr schrieb:
Welchen Timer würdest du in 1.4.2 vorschlagen?
Lies dir diesbezüglich doch mal folgenden Tread durch:
http://www.javagaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=2D;action=display;num=1083330360;start=
-
Danke.
Wenn ich die Debatte richtig verstanden habe, wird dort im Prinzip dasselbe empfohlen, wie ich über die JNI in C+ gemacht hätte. Nur dass Perf nicht in der API enthalten ist.
Die Wartezeit wird mittels yield() überbrückt.Was würdest du empfehlen? Einen Warten-bis-fertig-und-so-lange-yield Timer oder gibt es einen richtigen Timer, der angeschmissen wird und nach der gewünschten Zeitspanne eine Aufwach-Funktion aufruft?
Habe in C++ so einen Timer mal gesehen, der hat ein Event angelegt, das von Windows nach k ms aufgerufen wurde. Dann musste man lediglich die Message abfangen und gut wars. Aber das in JNI zu verpacken würde in meinen Augen nicht gehen, da ich dann in der DLL alle Messages überprüfen muss bis die richtige dabei ist. Ergo komme ich dort auch erst wieder raus wenn die Zeit um ist. Ausser ich mache dort einen separaten Thread, der nur die Messages überwacht... aber das sprengt dann definitiv den Rahmen.
so long,
exr
-
Hi
du solltest dir im klaren sein, das wenn mehrer threads die wait dll verwenden immer nur einer laufen kann. der andere wird solange vom OS auf eis gelegt (im normalfall hat man ja nur einen Prozessor). Je nach Länge der Zeitscheiben für die Threads kann es durch aus vorkommen, das dein wait länger wartet als angegeben, da es erst zu einem spähteren zeitpunkt wieder ausgeführt wird. ggf mal mit mehreren threas mal testen
gruss Termite
-
Selbst mit dem genausten Timer ist doch kein Verlass das das jede 10 ms aufgerufen wird.
-
@Termite_
OK, das wollte ich nur wissen. Danke!@jaaa
klar nicht. Nur: wenn ich einen 08/15 Timer nehme bekomme ich Streuungen dass es nicht mehr fröhlich ist.Im Moment baue ich gerade den Perf-Timer ein. Der funktioniert genausogut wie QueryPerformanceCounter und ich brauche keine JNI-DLL. Damit hat sich die Urpsrungsfrage gleich mit erledigt. Das einzige Problem das ich im Moment habe ist, dass einige Funktionen sporadisch länger als 10ms brauchen um durchzuarbeiten. Daher wird das Intervall durch diese Verzögerung durchbrochen. Jetzt muss ich "nur" noch rausfinden wo die Störenfriede ihren Ursprung haben...
thx nontheless :D,
exr
-
Hi
du solltest dir auch im klaren sein, das sowas bei paralellaufenden thrads immer passieren kann. Egal ob Java oder c/c++; unix/linux oder windows. Du kannst nie wissen wann das os deiner anwendung den Prozessor entzieht um in eine andere Anwendung zuzuteilt, oder wann dein thread den prozessor wiederkrigt nach dem er ihn abgegeben hat.
Selbst im embeded bereich mit RTOS braucht man ein bischen mehr gehirnschmalz um das sauber zum laufen zu kriegen ( Welcher prozess darf welchen unterbrechen, ohne dedloks und andere katastrofen zu produziehren)
aber noch viel spass beim debuggen. vorallem da das ein laufzeitproblem ist, die machen immber besonders viel spass. (im debug mode tuts einwandfrei, im run mode passiren fehler)
Kannst du die "fehler" reproduziehren oder treten die wirklich sporadisch auf?
gruss termite
-
Hallo.
Die Fehler sind in gewisser Weise reproduzuerbar, und ich habe es auch geschafft durch lokale Untersuchungen einzelner Funktionsaufrufe festzustellen wo die Verzögerungen herkommen.
Nachdem ich den ganzen Freitag vergeblich versucht habe das Problem zu beseitigen, habe ich heute morgen das Beta 1.5.0 aufgespielt, neu kompiliert und seitdem sind 99% der Timing-Probleme gelöst!Gruss,
exr