boost signals2 thread-safty



  • hey leute,
    hab mal wieder ein (wahrscheinlich dämliches) problem.

    #include <iostream>
    #include <boost/signals2/signal.hpp>
    #include <boost/thread.hpp>
    #include <stdio.h>
    
    // nur zum testwarten
    void wait (int seconds) {
      clock_t endwait;
      endwait = clock () + seconds * CLOCKS_PER_SEC ;
      while (clock() < endwait) {}
    }
    
    struct HelloWorld {
      int i;
      boost::signals2::signal<void ()> sig;
      void doit() {   // eigentlicher ablauf
        i++;
        wait(3);
        std::cout << "Hello, World! " << i << std::endl;
      }
      void send() {   // signal sender
        sig();
      }
      void operator()() { // startet signal im neuen thread
       boost::thread t(boost::bind(&HelloWorld::send, this));
      }
    };
    
    int main() {
    
      HelloWorld hello;
      hello.i=0;
    
      hello.sig.connect(boost::bind(&HelloWorld::doit, &hello));
    
        std::cout << "before" << std::endl;
      hello();
        std::cout << "after1" << std::endl;
      hello();
        std::cout << "after2" << std::endl;
      hello();
        std::cout << "after3" << std::endl;
       //t.join();
       wait(5);
    
      return 0;
    };
    

    und zwar steht in der beschreibung von signals2 das es threadsicher ist, jedoch ist die ausgabe

    before
    after1
    after2
    after3
    Hello, World! Hello, World! 3
    3
    Hello, World! 3
    

    die idee ist es das bei einem aufruf einer funktion ein signal gesendet wird, jedoch nicht auf das beenden des signals gewartet wird. deswegen lagere ich es in einen thread aus. kann mir da einer vllt sagen wo der fehler liegt?

    die ausgabe sollte dann

    before
    after1
    after2
    after3
    hello, world! 1
    hello, world! 2
    hello, world! 3
    

    sein.
    gruß pete



  • Was hat thread-Sicherheit mit der Rehenfolge zu tun? Wenn du nicht selber im Programm dafür sorgst, dass deine gewünschte Reihenfolge erzeugt wird, ist sie zufällig.



  • Keine Ahnung, aber sich and saftyge Threads wagen.



  • was für ne reihenfolge?



  • Was ist eine Klasse/Struct? Was ist ein Thread.



  • Deine Funktionen (=Slots) sind nicht threadsicher.
    Bei signals2 werden mit nichten die Slots automatisch synchronisiert. Nur die Verwaltung der Verbindungen wird synchronisiert. Du kannst nebenläufig Slots verbinden und trennen, ohne Dir Gedanken über Threadsicherheit machen zu müssen. Deine Funktionen (sprich, das Initiieren von Signalen und die dadurch ablaufenden Funktionen) werden dadurch aber nicht threadsicher. Zumindest nicht so, wie Du es machst.



  • hab mir schon gedacht das ich das falsch verstanden haben. dachte ich könnte mit signals auf mutex verzichten. dem ist wohl nicht so. danke tachyon



  • Du kannst nebenläufig Slots verbinden und trennen, ohne Dir Gedanken über Threadsicherheit machen zu müssen.

    Ich vermute du meinst das richtige, aber die Aussage stimmt so nicht ganz.

    Man kann nämlich schnell ein Problem bekommen, wenn man eine Connection auf eine Memberfunktion im Destruktor des Objekts trennt, während aus einem anderen Thread das Signal aufgerufen wird.
    Das "disconnect" kann nämlich vollständig ausgeführt werden, während der eigene Handler noch läuft. So löscht man der Memberfunktion das Objekt unterm Hintern weg. Nicht gut.

    "Ohne sich Gedanken zu machen" ist daher IMO einigermassen irreführend, da das beschriebene wohl kein ganz seltenes Szenario sein wird.
    (Zumindest ich habe es schon mehrfach gebraucht - hatte ja diesbezüglich auch kürzlich hier gefragt wegen Binden von "this" als weak_ptr)



  • Gab es dafür nicht die scoped connections? Also zum schließen einer Verbindung z.B. beim Zerstören eines Objekts?
    Ansonsten: Ja hast recht. Ich meinte eigentlich, dass nur das Verbinden/Trennen von Verbindungen sicher ist. Wenn man nebenläufig noch aktive Signale hat, muss man aufpassen.


Anmelden zum Antworten