Darf man das? boost.Thread + C++0x-Lambdas



  • Ich bin mir mit Threads und Lambdas und ihrem Zusammenspiel noch nicht so 100%ig sicher, daher hier einfach mal die Frage, ob folgendes "erlaubt" (definiertes Verhalten, portabel,...) ist. Es compiliert und läuft und liefert das richtige Ergebnis:

    #include <boost/test/unit_test.hpp>
    #include <boost/thread.hpp>
    
    BOOST_AUTO_TEST_CASE(testLambdaThread)
    {
      int i = 5;
      boost::thread incrementer([&](){ i += 2; });
      incrementer.join();
      BOOST_CHECK(i == 7);
    }
    

    Wird die capture im anderen Thread richtig rumgereicht und behandelt?



  • Klar, Lambdas sind doch auch nur Funktoren.



  • Ethon schrieb:

    Klar, Lambdas sind doch auch nur Funktoren.

    "nur" ist gut... ich bin mir halt mit dem ganzen Capture-by-Reference Gedöns nicht so richtig sicher...



  • Ev. hilft dieser Code:

    #include <boost/thread.hpp>
    #include <boost/assert.hpp>
    
    struct functor
    {
        explicit functor(int& i)
            : i_(&i)
        {
            std::cout << "functor constructed" << std::endl;
        }
    
        functor(const functor& other)
            : i_(other.i_)
        {
            std::cout << "functor copied" << std::endl;
        }
    
        void operator() ()
        {
            (*i_) += 2;
        }
    private:
        functor& operator==(const functor&);
    
        int* i_;
    };
    
    functor make_functor(int& i)
    {
        return functor(i);
    }
    
    int main()
    {
        int i = 5;
        {
            boost::thread incrementer([&](){ i += 2; });
            incrementer.join();
            BOOST_ASSERT(i == 7);
        }
        {
            boost::thread incrementer(make_functor(i));
            incrementer.join();
            BOOST_ASSERT(i == 9);
        }
    }
    


  • theta schrieb:

    Ev. hilft dieser Code:

    Dass es - falls es richtig läuft - so oder so ähnlich funktionieren muss, ist mir klar. Die Frage war nur, ob es beim Capture-by-Reference irgendeinen Haken gibt im Zusammenhang mit Threads. Aber scheint ja nicht so zu sein 😉



  • Haken gibt es einige. Selbst Herb Sutter (Mister Multithreading persönlich) hat mal auf seinem Blog einen Fehler in dieser Richtung gemacht:

    vector<thread> threads;
    for (int i=0; i<10; ++i) {
      threads.emplace_back([&]{
        ...Teilproblem i loesen...
      });
    }
    for (auto& t : threads) t.join();
    

    Wo ist der Fehler? --> Datenrennen und Kurzlebigkeit von i. i hätte kopiert werden müssen:

    [&,i]{
        ...Teilproblem i loesen...
    }
    


  • Das Problem hast Du mit Funktoren auch. Es ist prinzipiell ein Problem, wenn man Pointer / Referenzen auf Variablen verwendet, die nicht mehr existieren.



  • Naja, dass die references, die da gecaptured werden, nicht vor dem join danglen dürfen, ist klar 😉


Log in to reply