Smartpointer für Flag-Übergabe?



  • Gibt´s pro Container nur einen Thread? Falls ja, macht es Sinn, den Thread als Member des Container zu verwalten? Falls ja kannst du den Thread im Destruktor der Container Klasse beenden.



  • camper:
    Der von der Variable, die der Smartpointer kapselt. Ich habe gerade so was (schlagt mich bitte nicht zu hart, falls ihr das wollt):

    boost::shared_ptr<volatile bool> abortThread;
    

    initialisiert wird der im Elementinitialisierer der Klasse mit:

    Container::Container(/* ... */) : /* ... */, abortThread(new bool(false))
    

    Nach Kopie von Container ist *abortThread oder *abortThread.get() (falls die Syntax jetzt nicht stimmt: ich meine halt einfach den Wert des bools) true statt false! Warum? Weiß ich nicht, führe ich gerade auf mein Unverständnis von shared_ptr zurück, ich dachte, den dürfte man kopieren.

    Athar:
    Es ist nicht so supersauber, aber Container kommt aus einem Pool. Container hat sozusagen zwei States active und inactive. Kopiert wird das Ding nur in der inactive-Variante. Threads werden lediglich in der active-Variante genutzt. Es können aber während der Laufzeit eines Container s mehrere Threads (hintereinander! zu einem Zeitpunkt ist Container : Thread immer 1 : 0/1) ablaufen. Nur der letzte ausgeführte Thread kann wie gesagt über die Laufzeit von Container hinauslaufen. Das ist zwar nicht gewünscht, aber der lässt sich ja nicht einfach abrupt stoppen, nur weil ich das gerne hätte, oder? Meistens garantiert ein Abort oder so das nicht, soweit ich das im Kopf hab?!

    DocShoe:
    Genau das hätte ich ja gerne. Aber das Flag zum Aborten des Threads wird eben in Container verwaltet und der Thread hält eine Referenz drauf und prüft das ständig. Wenn Container stirbt, ist die Referenz nicht mehr gültig. Ich kann den Thread ja nicht so beenden, dass er mit Sicherheit keine Anweisung mehr ausführt, oder? Durch das Flag kriege ich ihn nach kurzer Zeit zum stoppen, aber u.U. dauert das zu lange und RRID hat das Flag, verwaltet von Container schon vernichtet. 😞



  • Eisflamme schrieb:

    Nach Kopie von Container ist *abortThread oder *abortThread.get() (falls die Syntax jetzt nicht stimmt: ich meine halt einfach den Wert des bools) true statt false! Warum?

    Schuss ins Blaue: im Destruktor setzt du das Flag auf true? Dann musst du wissen, dass beim Kopieren des Shared-Pointers (was implizit beim Kopieren von Container passiert) das Objekt (hier der bool) geteilt wird, d.h. die Kopie und der ursprüngliche Container beziehen sich über unterschiedliche Shared-Pointer auf dasselbe bool-Objekt. Wenn nun die Kopie zerstört wird (etwa, weil es eine temporäre Kopie ist), wird also das Flag true gesetzt und bezieht sich dann auch auf den ursprünglichen Container.

    Es gibt sicher bessere Möglichkeiten. Z.B. könnte ich mir vorstellen, dass es eine Besitzbeziehung zwischen Thread und Container gibt, womit du entweder den Thread zum Member des Containers machen kannst, oder andersherum den Container zum Member des Threads. Oder aber du arbeitest mit Callbacks, dass der Container dem Thread sein Zerstören mitteilt.



  • ipsec schrieb:

    Schuss ins Blaue: im Destruktor setzt du das Flag auf true?

    Dann könntest Du im Destruktor die Anzahl der shared_ptr auf Dein Flag abfragen und das Flag nur dann umschalten, wenn diese Anzahl kleiner als 3 ist. Denn bei 2 gibt es nur noch den in Deinem Thread und den in dem gerade zu zerstörenden Container.



  • Schuss ins Blaue

    Wohl eher ins Schwarze! Vielen Dank für die Erklärung, ich wusste, irgendwie so was Offensichtliches habe ich übersehen. Meine Vorgehensweise lädt einfach zu Fehlern ein, mir fällt aber nichts Besseres ein. Und jetzt lese ich Deinen zweiten Absatz.

    Es gibt sicher bessere Möglichkeiten. Z.B. könnte ich mir vorstellen, dass es eine Besitzbeziehung zwischen Thread und Container gibt, womit du entweder den Thread zum Member des Containers machen kannst, oder andersherum den Container zum Member des Threads. Oder aber du arbeitest mit Callbacks, dass der Container dem Thread sein Zerstören mitteilt.

    Na ja, es gibt schon eine Besitzbeziehung, die eben besagt, dass - falls es gerade einen Thread gibt - der bitte sterben soll, wenn der Container stirbt. Blöd ist halt, dass "Thread" hier eigentlich ein asynchroner Funktionsaufruf ist. Denn ich dachte, es wäre einfacher das so zu gestalten als es über einen Thread laufen zu lassen... Und den asynchronen Aufruf kann ich ja nicht so einfach beenden. 😞

    Aber auch wenn es ein Thread wäre: Ich will den Thread ja über ein Flag steuern können (zusätzlich zur Besitzbeziehung!). Und das Flag ist eben im Container beheimatet (Thread hat Referenz drauf). Ich kann ja tun, was ich will, der Thread kann einfach irgendwann noch versuchen wollen auf das Flag zuzugreifen. (was er ja eigentlich auch soll, wenn der Container im dtor das Flag auf false setzt, um dem Thread mitzuteilen, dass er jetzt bitte Mal aufhören soll) Ist der Container aber schon tot, ist auch das Flag weg und ein Test vom Thread auf das Flag führt zum Dump. Dafür war mein shared_ptr ja gedacht!



  • Belli schrieb:

    ipsec schrieb:

    Schuss ins Blaue: im Destruktor setzt du das Flag auf true?

    Dann könntest Du im Destruktor die Anzahl der shared_ptr auf Dein Flag abfragen und das Flag nur dann umschalten, wenn diese Anzahl kleiner als 3 ist. Denn bei 2 gibt es nur noch den in Deinem Thread und den in dem gerade zu zerstörenden Container.

    Noch einfacher:
    Im Destruktor machst Du gar nix. Im Thread machst Du statt einer Abfrage auf das Flag eine Abfrage auf die Anzahl der Referenzen, die noch auf Dein Flag existieren. Ist die kleiner als 2, dann ist der Thread der einzige, der noch einen shared_ptr auf Dein Flag hält, die Container sind alle tot ...



  • Stimmt, das ist tatsächlich einfacher!

    Also ist die Abbruchprüfung ptr.use_count() < 2 || *ptr

    Dankeschön!



  • Find´ das nicht schön...
    Was ist denn, wenn du ein kleines Event System baust? Der Container bietet als Producer ein OnDestroy an, auf das sich der Thread als Subscriber anmeldet. Im Destruktor setzt der Container ein Event ab, der Thread bekommt das mit und beendet sich.



  • Von Zeit zu Zeit möchte der Benutzer von Container gerne den Thread abbrechen können.

    Jaja, alles schon mal gelesen ... in der PPL.

    Ich wollte einen shared_ptr um das Flag herumwickeln.

    shared_ptr fuer ein Flag? Sinnfrei ...

    Wenn ein Thread abgebrochen werden soll, wird einfach sowas wie thread.stop() gemacht. Ueber thread.is_running() kann der aktuelle Status abgefragt werden und gegebenenfalls aus deinem Thread-Pool entfernt werden.



  • Thread hier ist nicht up-to-date, weil ich es inzwischen anders gelöst habe.

    shared_ptr fuer ein Flag? Sinnfrei ...

    Wenn ich die schlechte Struktur von vorher unbedingt hätte beibehalten wollen, wäre das eben eine Lösung für das Problem der Lebenszeit gewesen. Weiß nicht, ob Dir das bewusst war.

    Habe aber die Struktur verworfen und jetzt nen ThreadPool. Asynchrone Funktionsaufrufe kann man zwar mitnichten einfach stoppen, aber über das Flag kann ich die Aufrufe schnell beenden. Dann läuft der Aufruf aus und das Programm beendet sich automatisch danach, weil der dtor blockt. Klappt alles prima und ist jetzt auch sauber, wie ich finde 🙂


Anmelden zum Antworten