[gelöst] dtor von threadsafe_list aus "C++ Concurrency in Action": Warum remove_if?



  • Die Lambda, die im Destruktor dem remove_if übgeben wird, gibt doch immer true zurück. die Liste wird also einfach so abgeräumt. Eine andere remove mthode brint die Klasse ja nicht mit.



  • manni66 schrieb:

    Würde im Defaultdestruktur ein Nodenmutex gesperrt?

    Nein, aber müsste es?

    Praedikat schrieb:

    Die Lambda, die im Destruktor dem remove_if übgeben wird, gibt doch immer true zurück. die Liste wird also einfach so abgeräumt. Eine andere remove mthode brint die Klasse ja nicht mit.

    Ja, schon klar, aber wieso lässt man sie nicht auf "natürlichem Weg" aufräumen?


  • Mod

    Dobi schrieb:

    übersehe ich irgendwas fundamentales?

    Die Zerstörung eines mutex ist selbst nicht threadsafe. Mithin muss der zerstörende Thread für vorherige Synchronisation sorgen, andernfalls entstünde eine Race Condition (jedenfalls potentiell, das hängt davon ab, wie genau sicher gestellt wurde, dass alle operationen auf der Liste beendet sind), falls zuletzt ein anderer Thread den Mutex besessen hat.
    Ein anderer Grund ist möglicherweise der, dass der Defaultkonstruktor die Liste rekursiv löscht, was potentiell zu einem Stacküberlauf führen könnte.



  • Dobi schrieb:

    manni66 schrieb:

    Würde im Defaultdestruktur ein Nodenmutex gesperrt?

    Nein, aber müsste es?

    1. ein Mutex garantiert, dass alle Prozessoren den gleichen Speicherinhalt sehen. Vor C++ 11 war das auf jeden Fall notwendig, soweit ich weiss ändert das neue Speichermodell daran nichts, wenn man keine Atomic Variablen benutzt.

    2. warum sollte man darauf hoffen, dass schon alles gut geht, wenn man es absichern kann?



  • @manni66:

    1. Nach dem Zerstören sollte sich eigentlich kein Prozessor den Speicherinhalt noch angucken. 😉
    2. Es wäre ja kein blindes Hoffen, weil man ja genau wüsste, in welcher Reihenfolge die Liste im default dtor zerstört würde, was ja auch unter der oben genannten Voraussetzung kein Problem wäre.

    @camper: Na gut, ich hatte ihn so verstanden, dass für alle dtors in seinen Containern da die Grundvoraussetzung gilt, dass nach dem Start der Zerstörung kein anderer Thread mehr drauf zugreift. Wär also dann halt nur ein zusätzliches Sicherheitsding. Wundert mich halt, weil er das bei seinen anderen Containern (zb beim Stack) halt nicht macht. Der würde einem auch um die Ohren fliegen wenn man ihn zerstört während jemand anders noch drauf hantiert.
    Stacküberlauf ist auch ne interessante Idee. 🙂



  • Dobi schrieb:

    @manni66:

    1. Nach dem Zerstören sollte sich eigentlich kein Prozessor den Speicherinhalt noch angucken. 😉

    Der zerstörende Prozess sollte aber das zuletzt geschriebene sehen.



  • Muss natürlich Thread und nicht Prozess heissen



  • manni66 schrieb:

    Der zerstörende Thread sollte aber das zuletzt geschriebene sehen.

    Alles, was geschrieben wurde, war dabei doch eh schon in Mutexe verpackt. Die dann beim Zerstören noch ein zweites mal alle durchzulocken, ist also unnötig.



  • Dobi schrieb:

    manni66 schrieb:

    Der zerstörende Thread sollte aber das zuletzt geschriebene sehen.

    Alles, was geschrieben wurde, war dabei doch eh schon in Mutexe verpackt. Die dann beim Zerstören noch ein zweites mal alle durchzulocken, ist also unnötig.

    Nein, so funktioniert das nicht. Nachdem ein Mutex gesperrt wurde, ist garantiert, dass der sperrende Thread alles "sieht", was vorher geschreiben wurde. Mehr nicht!



  • Ah ok, das Locken einer Mutex hat acquire-semantik und das Unlocken zwar release-Semantik, aber wenn A schreibt, dann released und B danach nicht acquired, sieht B das was A geschrieben hat nicht unbedingt. Und hier im dtor muss der zerstörende Thread sehen, was andere vorher geschrieben haben, weil T ein Typ sein könnte, der in seinem dtor eventuell noch etwas tun will, richtig? 🙂



  • Ja, so meinte ich das.



  • Super, danke, das klingt sehr vernünftig.
    Edit: Oh, es geht ja nicht nur um die dtors der Instanzen von T, also von node::data, sondern auch darum, dass Änderungen an den besitzenden Verbindungszeigern node::next sichtbar sind. Wunderfein. 🙂

    Warum er das dann beispielsweise bei seiner threadsafe_queue nicht macht, weiß ich zwar nicht, aber das ist ja ein anderes Thema.


Anmelden zum Antworten