C++ `Timer` - Klasse Umsetzung
Ich entworfen habe ein Timer
Klasse, die löst (mit einem Observer-Muster) ein Ereignis jedes n
n-Sekunden. Natürlich schafft es einen neuen thread, um nicht den thread blockiert, hiess es aus.
Dann habe ich mir gedacht - hmmm... sagen wir mal 100 clients eine Verbindung zu meinem server-Programm, erstelle ich 3 Timer für jede von Ihnen, so dass ich laufen 300 threads. Ist es nicht viel? Ist es ein ok
, dass ich 300 threads?
Dann war ich gesagt, dass in AS3 - Timer
läuft im Haupt-thread. Und ich fragte mich: WIE??? Wie kann ich implementieren einen timer laufen im main thread und nicht es zu blockieren? Ist es möglich in C++?
- Die meisten (oder zumindest viele) timer-Implementierungen tatsächlich blockieren. Es ist nichts falsch mit, dass. Es hängt natürlich von dem Zweck, obwohl.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Eine mögliche Lösung besteht darin, nur einen thread für alle Timer und einer queue angeordnet durch den timeout. Das problem mit diesem ist, dass, wenn ein timer abläuft, und Sie rufen die callback-Funktion, die ausgeführt wird, im Kontext der globalen timer-thread und nicht einzeln.Dies kann natürlich gelöst werden, und erzeugt einen neuen thread nur für die Veranstaltung, die dann verbunden ist, direkt oder durch einen thread-pool für die Verarbeitung von Ereignissen, also der Haupt-timer-thread wird nicht "verstopft".
Können Sie ein einzelnes timer-thread, und für jeden client, "Register", erstellen Sie einen Eintrag im Baum. Der Schlüssel wäre die client-timeout und der Wert wäre eine Referenz an den client. Dies würde, um die Kunden von Ihren timeout.
Dann für den timer, stellen Sie einen zyklischen timer, sagen alle 100 Millisekunden (Stimmen entsprechend). Wenn der timer abläuft, Durchlaufen den Baum entfernen und Versand jeder client, der hat das Zeitlimit überschritten. Die iteration sollte stoppen, wenn Sie erreichen eine client timeout, dass nicht noch Zeitüberschreitung.
Genauer Verbesserung dieses Ansatzes wäre, wenn der Zeitgeber abläuft, und die Kunden versendet werden, berechnen Sie die Zeitspanne der nächsten client und stellen Sie den timer entsprechend. Es hängt nur davon ab, wie genau die Lösung sein muss.
Nun, dies ist eine design-Frage, so hat jeder unterschiedliche Meinungen und es hängt auch von deinen Anforderungen, aber IMO, der timer soll sich nicht entscheiden threading-Richtlinie selbst - sollte der Kunde das tun.
Ich bin mir nicht sicher, welches Verhalten Sie erwarten, aber wenn Sie laufen 300 Veranstaltungen auf einen timer auf dem gleichen thread und eine event-handler-Blöcke aus irgendeinem Grund, andere event-Handler wird nie ausgelöst werden.
Eine Möglichkeit ist, erstellen Sie einen timer auf einen thread, aber implementieren Sie in einer Weise, dass die event-Handler werden ausgeführt, andere threads über thread-pool. Natürlich, es ist immer noch möglich, die Dinge brechen, weil, wenn Sie haben viele lang laufende Handler-thread-pool bekommen könnte, erschöpft.
Ich empfehle dringend, nicht mit expliziter neuen thread für jeden handler, als Kontextwechsel würde wahrscheinlich töten die Leistung. Thread-pool ist viel besser auf die Vereinbarkeit dieser.
So weit wie die Implementierung eines timer in der main-thread geht, gibt es einen Mechanismus, der in regelmäßigen Abständen aufgerufen-user-code (z.B. bei event-polling), die sich auch mit dem Timer. Natürlich, ein solcher Ansatz ist wahrscheinlich ungenau, denn es kann nur ausführen, Timer, wenn der Benutzer code in der main-thread erlaubt.
Ist auch er verhindert, dass der Haupt-thread während der callback-code ausgeführt wird, natürlich.
Ihre erste Frage schon genug Antworten: Ein thread-pool (eine Gruppe von sagen wir 5 oder 10 Fäden), die sich mit der timer-Ereignisse ist der übliche Weg, dies zu tun und ein guter Kompromiss zwischen einem thread für jede Veranstaltung und ein thread für alle Ereignisse.
Bezüglich deiner zweiten Frage: Mit regelmäßigen Programmierung bedeutet, dass Sie nicht führen Sie die timer-event-handler in der main-thread. Wenn Sie könnte, würde es "block" Haupt-thread, aber das ist nicht möglich, ohne Zustimmung und Unterstützung aus der code-Ausführung im Haupt-thread.
Den Haupt-thread müsste dann halt von Zeit zu Zeit und überprüfen Sie, ob ein Ereignis vom timer, die Parameter aus, den timer in die form eines Gegenstandes und als das Ereignis behandeln. Es gibt viele Möglichkeiten zu entwerfen, dieses Prinzip, aber das ist die Allgemeine Art und Weise, wie Sie es tun.
Auf Unix-Systemen könnte man auch denken, der Verwendung von Signalen, aber ich glaube, dass ist keine gute Idee.
Dein server kann, führen Sie eine timer-thread für alle Timer. Diese
timer wheel
Ereignisse erzeugt, wenn der Kunden-Timer registriert werden, um die Server-timer-Rad. Wenn das eingetragene timer-Zeiten aus, die Veranstaltung wird durch das timer-Rad. Die clients erhalten den Griff auf der Veranstaltung erstellt, zu der Zeit war der timer registriert. Kunden können warten, für die Ereignisse, die Signalisierung der registrierten Zeitgeber eine Zeitüberschreitung. Diese Art der thread-Erstellung ist bis zu den Kunden.Da Sie die Konstruktion in C++ können Sie Boost-ASIO Timer für, die. Ich habe auch eine Timer-Klasse, die auf diesen basieren, und es funktioniert gut und ohne Gewinde - es nutzt asynchrone Aufrufe an die O. S., so dass im Grunde müssen Sie nur definieren Sie eine Rückruffunktion, die aufgerufen wird, wenn der timer abläuft und dann rufen Sie die timer - async_wait - Funktion, die nicht blockiert. Wenn Sie erklären, Ihre timer-Objekt, Sie müssen nur geben Sie einen io_service - Objekt, das die ASIO-Schnittstelle der O. S. Dieses Objekt ist verantwortlich für die Wartung Ihrer asynchronen Anfragen und Rückrufe, so zu tun, die Sie anrufen können Ihre Blockade-Methode laufen. In meinem Fall konnte ich nicht den Hauptthread blockieren, so hatte ich gerade ein thread, in dem diese einzigartige Anruf wurde blockiert.
Hier finden Sie Beispiele zur Verwendung der Boost ASIO asynchrone timer:
http://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio/tutorial/tuttimer2.html
Meine AbstractAsioTimer - Klasse entwickelt wurde, um die Unterklassen-also die onTimerTick Methode ist spezifisch für die abgeleitete Klasse endet. Obwohl Ihr braucht vielleicht ein wenig anders, ist es vielleicht ein guter Ausgangspunkt:
abstractasiotimer.hpp:
abstractasiotimer.cpp: