In Iteratorschleife Iterator löschen?



  • Hi,

    nein, hier geht es nicht um das berüchtigte erase()-Problem, sondern ich suche eine Hilfe, wie ich folgendes designen kann:
    Ich habe eine Schleife, die über eine std::list mit Nachrichtenempfängern läuft und an alle Empfänger, die eine bestimmte Bedingung erfüllen, eine Nachricht schickt (eine Methode der Empfängerklasse, von der alle Empfänger erben). Problem ist nur, dass diese Methode auch per unsubscribe()-Aufruf sich selbst aus der Liste entfernen darf, also das Empfangen der Nachricht beenden kann.

    Nur gibt es dann Probleme mit der übergeordneten Schleife... 😮

    Hoffentlich versteht ihr das Problem, falls nicht, kann ich es auch mit Code erläutern. 🙂

    ChrisM



  • Können denn die Empfänger nicht zurücksenden wenn sie sich selbst löschen müssen/möchten? Dann könntest du doch in deiner Schleife darauf reagieren, musst halt nur solange warten, bis eine Meldung kommt.
    Das heißt natürlich du musst auch senden falls sie sich nicht löschen, sonst wartest du ja ewig. Hmm so ganz gefallen tut mir diese Lösung allerdings auch nicht...



  • Hallo,

    Auf die Schnelle sehe ich 2 mögliche Lösungen.

    1. definiere den Iterator private in der Klasse.
    In Deiner unsubscribe-Methode kannst Du prüfen, ob der Iterator gerade auf dem Objekt steht, das du aus der Liste Löschst. Wenn ja, einfach den Iterator dekrementieren (Also auf das vorhergehende Objekt setzen, ich nehme an in der Schleife inkrementierst Du dann den Iterator wieder).

    Probleme: Du kannst die Methode mit der Schleife nicht rekursiv aufrufen (auch indirekt!).
    u.s.w.

    2. (andere Variante) Erzeuge einen temporären Zeiger auf Dein zu benachrichtigendes Objekt, und inkrementiere danach sofort den Iterator, und rufe dann erst die Benachrichtigungsmethode mit Hilfe des temporären Zeigers auf.

    Probleme: Wenn sich zu diesem Zeitpunkt nicht nur der Empfänger der Nachricht, sondern auch andere Objekte aus Deiner Liste löschen können, kann Dein Iterator immer noch ungültig werden.

    Vielleicht findest Du noch was besseres, würde mich interessieren, wie Du es gemacht hast.



  • Wenn die Liste nur Zeiger enthält, kannst du beim Unsubscriben auch einfach die Zeiger auf 0 setzen und regelmäßig per remove(0) rauskicken (bzw. SmartPtr-Äquivalent des Ganzen).



  • Hi,

    DJohns erste Lösung gefällt mir am besten, weil schön simpel. So werde ich es machen, denn die Schleife läuft maximal einmal pro Objekt (also keine Threadsicherheit hier nötig) und ruft sich auch nicht selbst auf. 🙂

    ChrisM


Anmelden zum Antworten