Ich schreibe gerade eine Multi-Thread-Anwendung mit Libevent.
Einige Ereignisse werden von IO ausgelöst, aber ich brauche ein paar Ereignisse, die über Threads vom Code selbst ausgelöst werden, mit event_active ().
Ich habe versucht, ein einfaches Programm zu schreiben, das zeigt, wo mein Problem ist:
Das Ereignis wird mit event_new () erstellt, und fd wird auf -1 gesetzt.
Wenn das Ereignis event_add () aufgerufen wird, wird das Ereignis später ordnungsgemäß von event_base_dispatch behandelt.
Wenn stattdessen event_add (ev, NULL) verwendet wird, wird 0 zurückgegeben (anscheinend erfolgreich), aber event_base_dispatch () gibt 1 zurück (was bedeutet, dass das Ereignis nicht ordnungsgemäß registriert wurde).
Dieses Verhalten kann mit dem folgenden Code getestet und die Zeile event_add vertauscht werden:
%Vor%Zusammenstellung: g ++ sample.cc -vent
Die Sache ist, ich brauche das Timeout nicht und möchte kein n-Jahre Timeout als Workaround verwenden. Wenn dies nicht der richtige Weg ist, um vom Benutzer ausgelöste Ereignisse zu verwenden, würde ich gerne wissen, wie es gemacht wird.
Ihr Ansatz ist gesund. In Libevent 2.0 können Sie event_active () verwenden, um ein Ereignis aus einem anderen Thread zu aktivieren. Stellen Sie nur sicher, dass Sie vorher evthread_use_windows_threads () oder evthread_use_pthreads () verwenden, um Libevent mitzuteilen, dass es die richtige Threading-Bibliothek verwenden soll.
Wenn Sie ein zusätzliches Ereignis benötigen: In Libevent 2.0 und früher wird eine Ereignisschleife sofort beendet, wenn keine ausstehenden Ereignisse hinzugefügt werden. Ihre beste Wette ist wahrscheinlich der Timeout-Trick, den Sie entdeckt haben.
Wenn Ihnen das nicht gefällt, können Sie die interne Funktion "event_base_add_virtual" verwenden, um der event_base mitzuteilen, dass ein virtuelles Ereignis vorliegt. Diese Funktion wird jedoch nicht exportiert. Sie müssen also Folgendes sagen:
%Vor%Das ist jedoch ein bisschen ein Hack, und es verwendet eine undokumentierte Funktion, also müsstest du aufpassen, falls es nicht mit einer späteren Version von Libevent funktioniert.
Schließlich hilft Ihnen diese Methode jetzt nicht, aber es gibt einen Patch für zukünftige Versionen von Libevent (2.1 und höher), um event_base_loop () ein neues Flag hinzuzufügen, damit es nicht beendet wird, wenn die Schleife keine Ereignisse mehr enthält . Der Patch ist über Github ; es wartet hauptsächlich auf Code-Überprüfung und auf einen besseren Namen für die Option.
Ich habe mich gerade mit libevent-2.0.21-stabil verbrannt. Es ist ganz klar ein Fehler. Ich hoffe, sie reparieren es in einer zukünftigen Version. In der Zwischenzeit wäre es hilfreich, die Dokumente zu aktualisieren, um uns zu warnen.
Die beste Problemumgehung scheint das falsche Timeout zu sein, wie in der Frage beschrieben.
@nickm, du hast die Frage nicht gelesen. Sein Beispielcode verwendet event_new () wie von Ihnen beschrieben; Es gibt einen Fehler in Libevent, der dazu führt, dass es fehlschlägt, wenn ein NULL-Timeout verwendet wird (aber 0 zurückgegeben wird, wenn Sie event_add () aufrufen).
Tags und Links libevent