komisches problem mit POSIX Thread...



  • in der 'void *TheServer::stWaitForMessages' fehlt übrigens ein rückgabewert 😉



  • ja dadran liegts auch ned... kann sein dass es n problem gibt wenn n nebenthread noch nen thread startet? ich bin das problem jetzt umgangen indem ich den 2. nebenthread überflüssig gemacht hab...

    danke dir, Hunger



  • pthread_create funktioniert NUR mit einem einfachen function pointer, NICHT mit einem member function pointer.
    die funktion darf teil einer klasse sein, dann muss sie aber "static" sein, damit es eben wieder ein normaler function pointer wird.



  • hustbaer schrieb:

    die funktion darf teil einer klasse sein,

    Strenggenommen nichtmal das. Die Funktion muss extern "C" void ()(void) sein.

    Es funktioniert zwar oft (wenn nicht zur Zeit immer) mit einer statischen Methode, es steht aber nirgends geschrieben dass eine statische Methode dasselbe Calling-Interface haben muss wie eine freie extern "C" Funktion, ist also per se "nicht portabel".



  • Huch, das wusste ich nicht, sorry! *schäm*

    Aber wenigstens lässt sich das leicht "thunken", da man ja einen void* Parameter hat netterweise. (Ich darf garnicht dran denken dass es immer noch Callback-Funktionen gibt die KEINEN "void* userdata" o.ä. haben, sonst werd' ich gleich wieder unrund...)

    Natürlich kann man so auch echte Memberfunktionen "einwickeln", ein kleines Template genügt ja.



  • ja des hab ich ja schon öfter geamcht die funktion is static daran lags ja nich aber is ja auch egal der thread war überflüssig



  • DaHunger schrieb:

    doch mags schon ich habs ja schon ausprobiert an andrer stelle des macht ja die sache so komisch es geht 2 mal und jetzt grad ned... und leer funktioniert die funktion... also wenn des ned komisch is...

    Das klingt sehr nach dem Problem über das wir uns schn mal ausgetauscht hatten.

    - Thread I ("main"-Thread) erzeugt Objekt o als Stackvariable;
    - Thread I erzeugt Thread II mit (void*) &o als Argument;
    - Thread I läuft weiter und vernichtet o am Ende des Blocks
    - Thread II will aber (&o)->irgendwas() aufrufen

    Obs (noch) gut geht oder (schon) nicht mehr hängt dann vom Scheduling ab; wirkt also ggf. zufällig!

    Grüsse

    *this



  • nene so wars bei mir bisher nich:
    Thread I erzeugt ein Objekt der Klasse K
    der Konstruktor der Klasse K enthält eine Endlosschleife (!!!)(bzw eine funktion die danach aufgerufen wird von außerhalb)
    bei jedem durchlauf dieser schleife wird auf ein client gewartet und mit diesem dann
    Thread II gestartet der eine statische funktion der Klasse K ausführt. als parameter übergibt er das objekt selbst und den client.
    die statische funktion ruft eine nicht-statische funktion des objektes auf und übergibt als parameter den client.

    Das objekt existiert also immer noch! was aber NICHT geht ist, dass Thread II jetzt einen Thread III startet der ähnlich funktioniert wie der aufruf von Thread II während Thread I (der Hauptthread) beliebig viele Threads Parallel starten kann.

    scheint wohl einafch so zu sein 🙄

    aber eine so kroteske konstellation sollte denke ich von grund auf überdacht werden wo irgendwelche nebenthreads noch weiter nebenthreads starten... hab ich getan unds geschafft ohne auszukommen was diskutiern wir hier noch? XD



  • Weiss auch nicht was du noch hier schreibst, der von dir ursprünglich gepostete Code ist grundfalsch, warum hat Gast++ beschrieben.

    Was du jetzt schreibst kann ich nicht nachvollziehen, ist leider etwas konfus.

    void TheServer::startWaitingForMessages(int _client){ 
        struct theServerClient client; // <-- Problem Teil 1
        client.server= this; 
        client.client=_client; 
        pthread_t thread; 
        pthread_create(&thread,NULL,stWaitForMessages,&client); // <-- Problem Teil 2
    }
    

    Du übergibst die Adresse von "client" an den neuen Thread, diese Adresse wird aber sofort nach dem pthread_create Aufruf ungültig, da es sich um ein lokales Objekt handelt. Wenn der neue Thread schnell genug losläuft geht es, wenn er zu spät losläuft geht es nicht. Das ist das Problem.

    Wenn der echte Code mit dem du Probleme hast anders aussieht solltest du vielleicht den posten. Üblicherweise macht man sowas eher so:

    void* TheServer::stWaitForMessages(void* _arg){ 
        std::auto_ptr<theServerClient> client(static_cast<theServerClient*>(_arg)); // ownership übernehmen
    
        // ...
        return 0;
    }
    
    void TheServer::startWaitingForMessages(int _client){ 
        std::auto_ptr<theServerClient> client(new theServerClient);
        client->server= this; 
        client->client=_client; 
        pthread_t thread; 
        if (pthread_create(&thread,NULL,stWaitForMessages,client.get()) == 0)
        {
            // success, "client" gehört jetzt dem Thread
            client.release();
        }
        else
        {
            // fehler, "client" soll vom auto_ptr freigegeben werden
        }
    }
    


  • achso jetz versteh ich das was gast++ gemeint hat,
    aber ich glaube nich dasses daran lag zumindest nicht ausschließlich. Grundfalsch würd ich das nich nennen ich müsste nur die variable wieder global machen...



  • Nein, du hast Recht, das ist noch eine Stufe falscher als grundfalsch. Hätte ich das in der Arbeit gesehen wäre ich ausgeflippt und hätte mich 10 Min. nichtmehr beruhigt.



  • hustbaer schrieb:

    Nein, du hast Recht, das ist noch eine Stufe falscher als grundfalsch. Hätte ich das in der Arbeit gesehen wäre ich ausgeflippt und hätte mich 10 Min. nichtmehr beruhigt.

    Dazu könnte man noch beachten dass der OP schon eine solche "Diskussion" um genau das Thema mit mir hatte http://www.c-plusplus.net/forum/viewtopic-var-t-is-110668.html
    Insofern grenzt das hier auch noch an ein Doppelposting.

    DaHunger schrieb:

    scheint wohl einafch so zu sein 🙄

    Nein, ist es nicht. Dein Code ist dubios.

    DaHunger schrieb:

    hab ich getan unds geschafft ohne auszukommen was diskutiern wir hier noch? XD

    Wenn ich sowas lese kommt mir echt die Galle hoch...
    Du bist weit davon entfernt mit irgendjemandem über Threads "diskutieren" zu können!
    Wenn ich sehe dass Du nach meinem Hinweis mit dem Singleton nicht die Instanz sonern die Klasse "TheServer" genannt hast sehe ich zudem wie ungenau Du diese Dinge durchdenkst.

    Aber - Dein Wille ist mir Befehl - nochmal werde ich mir sicher nicht Dein Geschreibsel ansehen!

    Grüsse

    *this



  • ich weiß zwar grad ned was du mit den singletons willst, ich hab keine peilung was des sein soll, hatte ich auch nich als du mirs erste mal n link geschickt hast

    warum ist mein code denn bitte "grundfalsch"?

    ach und, ja tut mir sehr leid dass ich euch 3 mal darauf hingewiesen hab, dass mein problem gelöst ist und ihr euch daher nicht weiter damit befassen müsst...

    wisst ihr was ihr habts geschafft, ich hab kb mehr auf des forum, wollte zwar eigentlich etwas aktiver hier werden aber wenn ich so was les dann vergeht mir die lust wieder

    tschö
    gruß, hunger



  • Weil du schätzomativ mal garnix nicht verstanden hast, deswegen "befassen wir uns damit noch weiter".

    Wenn du z.B. die "Variable" (Struktur/Objekt) einfach global machst überlebt "sie" zwar das Verlassen von "startWaitingForMessages", bloss knallts dann irgendwann mal weil "startWaitingForMessages" zu schnell hintereinander aufgerufen wurde, und die "globale Variable" dann beim Loslaufen von Thread N bereits mit den Daten für Thread N+1 überschrieben wurde.

    Natürlich kannst du all diese Dinge mit "sowas geht dann eben wohl nicht" abtun, kann dir keiner verbieten, nur dass es nicht stimmt. Gehen tut fast alles, bloss muss man es eben richtig machen. Und nicht falsch.


Anmelden zum Antworten