Referenz an std::thread



  • Hallo liebes Forum,

    ist es möglich eine Referenz an einen std::thread zu übergeben?

    Also ungefähr so:

    #include <thread>
    #include <vector>
    #include <iostream>
    
    struct meineStruktur
    {
        int val;
    }
    
    void foo(meineStruktur&);
    
    int main()
    {
        std::vector<meineStruktur> y;
        meineStruktur z;
        for(int i = 0; i < 10; i++)
        {
            z.val = 0;
            y.push_back(z);
            std::thread th(foo,y[i]);
            th.detach();
        }
        for(meineStruktur& v:y)
            std::cout << v.val << std::endl;
    }
    
    void foo(meineStruktur& x)
    {
        x.val = -3;
    }
    

    So ähnlich habe ich es bei mir im Code, allerdings verändert er den Wert nicht.



  • Sagt wer?
    Könnte doch sein, dass dein CPU-Scheduler dem Thread (bzw. den Threads) erst relativ spät Rechenzeit gibt und diese die Werte erst nach der Ausgabe ändern.

    Andererseits,v ersuchs mal mit einem Lambda-Ausdruck um deine Funktion aufzurufen.
    Und wenn das Problem dann noch bleibt, ersetz mal das detach durch ein join.



  • Sorry für die falsche Angabe.
    Eig. sieht der Code vielmehr so aus:

    #include <thread>
    #include <vector>
    #include <iostream>
    
    struct meineStruktur
    {
        int val;
    }
    
    void foo(meineStruktur&);
    
    int main()
    {
        std::vector<meineStruktur> y;
        meineStruktur z;
        int i = 0;
        while(true)
        {
            for(meineStruktur& v:y)
                 std::cout << v.val << std::endl;
            z.val = 0;
            y.push_back(z);
            std::thread th(foo,y[i]);
            th.detach();
            i++;
        }
    }
    
    void foo(meineStruktur& x)
    {
        x.val = -3;
    }
    


  • Die Lösung des Problems ist std::ref() 🙂



  • vector::push_back kann zu einer Re-Allocation führen. Dabei wird ein neues Array im vector angefordert, die Objekte rüberkopiert (bzw. rübergemoved), und danach wird das alte Array freigegeben.
    Und dabei werden natürlich alle Referenzen auf Objekte im vector ungültig die vor dem push_back ermittelt wurden.

    D.h. dein Code wird ein Problem bekommen, sobald mal über die Referenz zugegriffen wird nachdem in main() push_back aufgerufen wurde, und dieser Aufruf zu einer Re-allocation geführt hat.

    Du solltest statt dessen einen ptr_vector (Boost) verwenden, oder ggf. einen vector<unique_ptr> .



  • hustbaer schrieb:

    D.h. dein Code wird ein Problem bekommen, sobald mal über die Referenz zugegriffen wird nachdem in main() push_back aufgerufen wurde, und dieser Aufruf zu einer Re-allocation geführt hat.

    Du solltest statt dessen einen ptr_vector (Boost) verwenden, oder ggf. einen vector<unique_ptr> .

    In deque bleiben die Referenzen gültig, solange kein insert oder remove in der Mitte stattfindet. In list bleiben sie sogar immer gültig.



  • Danke für den Tipp ich werde es mal versuchen.
    Brauch ich dann std::ref() trotzdem, weil std::thread die parameter ja nur als call-by-reference übergibt wenn ich eben diesen reference-wrapper nutze? 🙂



  • Ja, brauchst du trotzdem.
    Es sei denn du übergibst einen Zeiger.
    Nur nen unique_ptr kannst du nicht übergeben, der ist ja nicht kopierbar. Bliebe einzig noch die Möglichkeit nen rohen Zeiger zu übergeben.


Anmelden zum Antworten