pthreads Thread wird nicht gestartet



  • Ich würde ans Ende jeder Funktion (auch der main ) einfach ein pthread_exit(NULL) setzen, des ermöglicht, dass z.b. die main wartet, bis alle Threads zu Ende gelaufen sind und sich erst dann beendet. Im Übrigen, wenn du mit pthread_join arbeitest, kannste als Argument von pthread_exit() deinen Rückgabe-Wert setzen. Wie das genau geht, ist auch in Manpages nachzulesen (zur Not die manpages-dev nachinstallieren).



  • Hi,
    Danke für eure Antworten.
    Wenn ich es mit den static_cast mache bekomme ich beim übergeben des structs auf pthread_create folgenden Fehler:

    data*« kann nicht nach »const pthread_attr_t*« für Argument »2« nach »int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)« umgewandelt werden
    

    In dem struct ist ein integrer und ein char array!

    MFG ReduX :xmas1:



  • Was genau verstehst du von der Fehlermeldung nicht?

    pthread_chreate nimmt 4 argumente.

    #1 ist der Thread den du erzeugen willst.
    #2 Sind die Attribute des Threads ie »Joinable«
    #3 ist die Funktion, die der Thread ausführen soll
    #4 ist das Argument das du an die Funktion weitergeben willst.

    Wenn du als 2. Parameter eine eigene Struct verwenden willst ist das schlichtweg FALSCH, dafür ist der 4. Parameter da.



  • Hi,
    Danke für deine Hilfe.
    Wenn ich das so abändere bekomme ich folgenden Fehler:

    Fehler: Argument des Typs »void* (ldp::client::)(void*)« passt nicht zu »void* (*)(void*)«
    

    Habe es aber genau so gemacht wie es weiter oben gepostet wurde!

    MFG ReduX :xmas1:



  • Du kannst als Thread-Funktion nur statische Memberfunktionen und Gelöste Funktionen verwenden. »Normale« Klassenfunktionen funktionieren hier nicht. (Du kannst höchstens als 4. Parameter einen Zeiger auf ein Objekt übergeben und über diesen Zeiger wieder eine Klassenfunktion starten.



  • Hi,
    Also bei mir ist es so das die threads in der klasse gestartet werden, dann ist die Klassenfunktion für sie doch ganz normal oder?
    Bsp.:

    struct data {
    char array[4096];
    int len;
    compile func;
    }
    class MEINECLASSE {
    private:
    void* empfangen(void *arg); //compile ist ein typedef für einen Funktionszeiger!
    public:
    void* empfang(compile funktion); //In dieser Funktion werden die Threads gestartet,diese rufen dann empfangen auf!
    };
    

    MFG ReduX :xmas1:



  • Eine Klassenfunktion hat einen impliziten Parameter: Den this-Pointer. Da die pthread-Bibliotek keinerlei Ahnung von C++ hat (ein C Bibliotek ist) kann sie auch den this-Pointer nicht mit übergeben -> nur staische Klassenmember (haben keinen this-Pointer!) und globale Funktionen können direkt gestartet werden.

    Workaround:

    class Threaded
    {
    public:
      void start_thread() {pthread_create([], [], &helper, this);}
    private:
      static void helper(void * ptr){static_cast<Threaded>(ptr)->thread_fun();}
      void thread_fun();
    }
    
    int main()
    {
      Threaded foo;
      foo.start_thread();
      pthread_exit(0);
    }
    


  • Wenn du schon C++ verwendest, wieso nutzt du nicht alle Vorteile von C++? Anstatt einfach Boost::Thread zu verwenden, plagst du dich mit C-threads rum?



  • Hi,
    Ja ich möchte möglichst keine fremden libs verwenden. Außerdem geht es mir noch um den lern-Faktor. Ich will nicht einfach das Programm fertig haben, sondern möchte dabei etwas lernen.

    MFG ReduX :xmas1:



  • @ReduX: das is echt die richtige einstellung 🙂



  • DEvent schrieb:

    Wenn du schon C++ verwendest, wieso nutzt du nicht alle Vorteile von C++? Anstatt einfach Boost::Thread zu verwenden, plagst du dich mit C-threads rum?

    boost::thread war im Umfang das letzte mal als ich mir das angesehen habe noch recht eingeschränkt 😉



  • Hi,
    Irgendwie habe ich nun keine Idee mehr, ich habe mir mal das workaround vorgenommen das gepostet wurde und das ist dabei herausgekommen:
    Header:

    struct data {
      char array[4096];
      int len;
      compile funktion;
    };
    class client {
      private:
    //blabla
     static void* helprecive(void *arg);
     static void* helpsend(void *arg);
     void emfpange(compile func);
     void sending(char buffertosend[4096]);
      public:
    //blabla
    void send2server(char buffertosend[4096]);
    void recv2server(compile func);
    };
    

    CPP:

    void network::client::send2server(char buffertosend[4096]) {
        data foo;
        int t = strlen(buffertosend);
        for(int i=0;i<t;i++) {
        foo.array[i]=buffertosend[i];
        }
        #ifdef WIN32
    
        #else
        pthread_t t1;
        pthread_create(&t1,0,helpsend,&foo);
        #endif
    }
    static void* network::client::helpsend(void* arg) {
        sending(static_cast<data*>(arg)->array);
    }
    void network::client::sending(char buffertosend[4096]) {
     //blabla
    }
    void network::client::recv2server(compile func) {
        if(empfange == false) {
        data funktion;
        funktion.funktion = func;
        #ifdef WIN32
    
        #else
        pthread_t t1;
        pthread_create(&t1,0,helprecive,&funktion);
        #endif
        }
    }
    static void* network::client::helprecive(void* arg) {
    compile func = static_cast<data*>(arg)->funktion;
    empfange(func);
    }
    void network::client::empfange(compile func) {
    //blabla
    func(recvbuffer,strange);
    }
    

    Werde dabei mit Fehlermeldungen überflutet:

    /home/server/Desktop/networklib/network.cpp:43: Fehler: Elementfunktion »static void* network::client::helpsend(void*)« kann nicht deklariert werden, statische Bindung zu haben
    /home/server/Desktop/networklib/network.cpp: In static member function »static void* network::client::helpsend(void*)«:
    /home/server/Desktop/networklib/network.cpp: At global scope:
    /home/server/Desktop/networklib/network.cpp:61: Fehler: Elementfunktion »static void* network::client::helprecive(void*)« kann nicht deklariert werden, statische Bindung zu haben
    /home/server/Desktop/networklib/network.h: In static member function »static void* network::client::helprecive(void*)«:
    /home/server/Desktop/networklib/network.h:28: Fehler: ungültige Verwendung des Elementes »network::client::empfange« in statischer Elementfunktion
    /home/server/Desktop/networklib/network.cpp:63: Fehler: von dieser Stelle
    /home/server/Desktop/networklib/network.cpp: At global scope:
    /home/server/Desktop/networklib/network.cpp:65: Fehler: keine Elementfunktion »void network::client::empfange(void (*)(char*, int))« in Klasse »network::client« deklariert
    /home/server/Desktop/networklib/network.cpp: In member function »void network::client::empfange(void (*)(char*, int))«:
    /home/server/Desktop/networklib/network.cpp:66: Fehler: invalid use of member (did you forget the »&« ?)
    /home/server/Desktop/networklib/network.cpp:69: Fehler: invalid use of member (did you forget the »&« ?)
    

    Habe da den Durchblick verloren 😞

    MFG ReduX :xmas1:



  • Du kannst aus der statischen Funktion keine »normalen« Memberfunktionen aufrufen.

    Daher auch der Vorschlag this als argument zu übergeben, da du static_cast<Server>(this)->funktion() aufrufen kannst.



  • Hi,
    Wie kann ich dann aber Parameter übergeben?
    Weil das was der User bei dem Funktionsaufruf übergibt brauch ich ja dann noch in der Funktion die vom Thread gestartet wird!

    MFG ReduX :xmas1:



  • entweder du baus dir eine struct, die sowohl die daten als auch »this« anthält oder du speicherst die Daten in einem Member deines Objektes zwischen.



  • Hi,
    Ich speichere es nun als Member bekomme jedoch noch ein paar Fehler:
    Header:

    class client {
      private:
    //blabla
     static void helprecive(void *arg);
     static void helpsend(void *arg);
     void emfpange();
     void sending();
      public:
    /blabla
    void send2server(char buffertosend[4096]);
    void recv2server(compile func);
    };
    

    cpp:

    void network::client::send2server(char buffertosend[4096]) {
       //blabla
        pthread_t t1;
        pthread_create(&t1,0,&helpsend,this);
        }
    }
    static void network::client::helpsend(void* arg) {
        static_cast<client>(arg)->sending();
    }
    void network::client::sending() {
    //blabla
    }
    

    Fehler:

    /home/server/Desktop/networklib/network.cpp:41: Fehler: ungültige Umwandlung von »void (*)(void*)« in »void* (*)(void*)«
    /home/server/Desktop/networklib/network.cpp:41: Fehler:   Argument 3 von »int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)« wird initialisiert
    /home/server/Desktop/networklib/network.cpp: At global scope:
    /home/server/Desktop/networklib/network.cpp:45: Fehler: Elementfunktion »static void network::client::helpsend(void*)« kann nicht deklariert werden, statische Bindung zu haben
    /home/server/Desktop/networklib/network.cpp: In static member function »static void network::client::helpsend(void*)«:
    /home/server/Desktop/networklib/network.cpp:46: Fehler: keine passende Funktion für Aufruf von »network::client::client(void*&)«
    /home/server/Desktop/networklib/network.cpp:2: Anmerkung: Kandidaten sind: network::client::client(char*, int, bool)
    /home/server/Desktop/networklib/network.h:20: Anmerkung:                  network::client::client(const network::client&)
    

    Die Fehlermeldungen beziehen sich auf den oben geposteten Code.

    MFG ReduX :xmas1:



  • static void network::client::helpsend(void* arg) { 
        static_cast<client>(arg)->sending();}
    

    =>

    static void * network::client::helpsend(void* arg) { 
        static_cast<client*>(arg)->sending();return 0;}
    

    Die funktion gibt void* zurück und du castest auf client*



  • Hi,
    Habe nun alles soweit hinbekommen. Jedoch bekomme ich noch bei der deklaration der static funktion folgenden Fehler:

    Fehler: Elementfunktion »static void* network::client::helprecive(void*)« kann nicht deklariert werden, statische Bindung zu haben

    Mein C++ Buch hat da leider auch keine antwort darauf.

    Frohes Neues noch!
    MFG ReduX


Anmelden zum Antworten