boost::thread will nicht funktionieren



  • Hallo zusammen,

    folgendes Problem: Ich habe 2 while-Schleifen mit dem gleichen Abbruchkriterium. Bei der einen handelt es sich um eine permanente Ausgabe auf das Terminal, bei der anderen um Keyboard-Eingaben, die jederzeit erfolgen können (sollen). Deswegen 2, weil ihr jeweiliger Code nicht hintereinander ausgeführt werden soll, sondern gleichzeitig.
    Nach einigem googeln habe ich herausgefunden, dass ich 2 Threads benötige. Also hab ich Boost heruntergeladen.

    Bereits unabhängig von meinem eigentlichen Problem: Selbst diese Codebeispiele funktionieren nicht. Das sagt g++ zum ersten Beispiel:

    g++ tmp.cpp -I ../../../Library/boost_1_45_0/
    Undefined symbols:
    "boost::this_thread::sleep(boost::posix_time::ptime const&)", referenced from:
    void boost::this_thread::sleepboost::posix\_time::seconds(boost::posix_time::seconds const&)in ccffrXiI.o
    "boost::detail::thread_data_base::~thread_data_base()", referenced from:
    boost::detail::thread_data<void ()()>::~thread_data()in ccffrXiI.o
    boost::detail::thread_data<void (
    )()>::~thread_data()in ccffrXiI.o
    "vtable for boost::detail::thread_data_base", referenced from:
    boost::detail::thread_data_base::thread_data_base()in ccffrXiI.o
    "boost::thread::join()", referenced from:
    _main in ccffrXiI.o
    "typeinfo for boost::detail::thread_data_base", referenced from:
    typeinfo for boost::detail::thread_data<void ()()>in ccffrXiI.o
    "boost::thread::~thread()", referenced from:
    _main in ccffrXiI.o
    _main in ccffrXiI.o
    "boost::thread::start_thread()", referenced from:
    boost::thread::thread<void (
    )()>(void ()(), boost::disable_if<boost::is_convertible<void (&)(), boost::detail::thread_move_t<void ()()> >, boost::thread::dummy>::type)in ccffrXiI.o
    ld: symbol(s) not found
    collect2: ld returned 1 exit status

    Wie man sieht, macht der Linker Probleme. Der Pfad zu boost ist jedenfalls Korrekt. Aber das "nur nebenbei". Und hier meine eigentliche Ausgabe nach Kompilierversuch:

    g++ spielesammlung.cpp -I ../../../../Library/boost_1_45_0/ -lcurses
    In file included from spielesammlung.cpp:5:
    pong/pong.hpp: In member function ‘void pong::play()’:
    pong/pong.hpp:92: error: no matching function for call to ‘boost::thread::thread(<unresolved overloaded function type>)’
    ../../../../Library/boost_1_45_0/boost/thread/detail/thread.hpp:215: note: candidates are: boost::thread::thread(boost::detail::thread_move_tboost::thread)
    ../../../../Library/boost_1_45_0/boost/thread/detail/thread.hpp:201: note: boost::thread::thread(F, typename boost::disable_if<boost::is_convertible<T&, boost::detail::thread_move_t<T> >, boost::thread::dummy*>::type) [with F = void (pong::)()]
    ../../../../Library/boost_1_45_0/boost/thread/detail/thread.hpp:154: note: boost::thread::thread()
    ../../../../Library/boost_1_45_0/boost/thread/detail/thread.hpp:122: note: boost::thread::thread(boost::detail::thread_data_ptr)
    ../../../../Library/boost_1_45_0/boost/thread/detail/thread.hpp:113: note: boost::thread::thread(boost::thread&)
    pong/pong.hpp:94: error: no matching function for call to ‘boost::thread::thread(<unresolved overloaded function type>)’
    ../../../../Library/boost_1_45_0/boost/thread/detail/thread.hpp:215: note: candidates are: boost::thread::thread(boost::detail::thread_move_tboost::thread)
    ../../../../Library/boost_1_45_0/boost/thread/detail/thread.hpp:201: note: boost::thread::thread(F, typename boost::disable_if<boost::is_convertible<T&, boost::detail::thread_move_t<T> >, boost::thread::dummy
    >::type) [with F = void (pong::*)()]
    ../../../../Library/boost_1_45_0/boost/thread/detail/thread.hpp:154: note: boost::thread::thread()
    ../../../../Library/boost_1_45_0/boost/thread/detail/thread.hpp:122: note: boost::thread::thread(boost::detail::thread_data_ptr)
    ../../../../Library/boost_1_45_0/boost/thread/detail/thread.hpp:113: note: boost::thread::thread(boost::thread&)

    Die Fehlermeldung bezieht sich auf folgenden Code (innerhalb einer Klasse):

    void ball_moves(){
      while(A.get_lifes()!=0 && B.get_lifes()!=0){
        //einige Zeilen
      }
    }
    
    void key_events(){
      int c = 0;
      while(A.get_lifes()!=0 && B.get_lifes()!=0){
        //einige Zeilen
      }  
    } 
    
    void play(){
      boost::thread t1(ball_moves); 
      t1.join(); 
      boost::thread t2(key_events);
      t2.join();
    }
    

    Die betreffenden Zeilen 92 und 94 aus der Fehlermeldung sind in diesem Fall 15 und 17. Offensichtlich gibt es keine passenden Konstruktor von boost::thread::thread für mein Vorhaben. Aber warum nicht? Was unterscheidet meinen Code vom Codebeispiel (und Linkerprobleme gibt es hier komischerweise auch nicht??)?

    Ich bin Neuling, was Boost angeht: Was mache ich falsch? (Und schon mal vielen Dank im Voraus :))



  • Hast du den C++0x Support bei deinem Compiler aktiviert? boost::thread benötigt C++0x, soweit ich weiß.



  • 314159265358979 schrieb:

    Hast du den C++0x Support bei deinem Compiler aktiviert? boost::thread benötigt C++0x, soweit ich weiß.

    Das stimm nicht...
    Außerdem gäbe das (glaub ich) eine Compiler-Fehlermeldung und keine vom Linker...

    Du musst die Library mitlinken.

    Dazu brauchst du in deinem Aufruf einen Verweis auf deine .a-Datei oder auf deine .dylib, wenn du dynamisch linken willst

    Bei mir sieht der Aufruf etwa so aus:

    g++ thread.cpp -I/opt/local/include/ -o thread /opt/local/lib/libboost_thread-mt.a
    

    Gruß,
    XSpille



  • Ahh, okay - dass ich das aktivieren muss hat mir noch keiner gesagt.
    Mir schnell mal das hier angeguckt. Und was soll ich sagen: Es klappt nicht.
    "man gcc" ausgeführt und da sieht man dann auch warum: wird nicht unterstützt. Ich hab gcc 4.2.1, das ist zu alt. Ich werde mal versuchen, eine neuere Version zu installieren.

    //edit
    @XZille: Ouh, kannst du das ein wenig ausführlicher beschreiben? Was für eine .a Datei? Ich hab noch nicht so häufig mit was anderem als der Standardbibliothek gearbeitet und bin deswegen auch mit Librarys linken etc. noch wenig vertraut.
    //edit2
    hier steht bei Thread: "Build & Link.... Automatic linking". Was sagt mir das jetzt? Muss ich doch nichts zusätzlich linken?



  • g0nz0 schrieb:

    @XZille: Ouh, kannst du das ein wenig ausführlicher beschreiben? Was für eine .a Datei? Ich hab noch nicht so häufig mit was anderem als der Standardbibliothek gearbeitet und bin deswegen auch mit Librarys linken etc. noch wenig vertraut.

    Als du boost installiert hast, hat er irgendwo diese Dateien erstellt.
    Wo kann ich dir leider nicht sagen.
    (Ich kenn ja nichtmal dein OS)
    Ich hab die auch suchen müssen. Vermutlich in irgendeinem lib-Verzeichnnis

    Ein Update von gcc kann sicher nicht schaden, aber wie gesagt, du brauchst kein C++0x

    My-MacBook-Pro:test Spille$ g++-4.2 thread2.cpp -I/opt/local/include/ -o thread /opt/local/lib/libboost_thread-mt.a
    My-MacBook-Pro:test Spille$ g++-4.2 --version
    i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
    Copyright (C) 2007 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions. There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.



  • Hmm,

    ganz egal wie ich es kompiliere...
    riesig inkl. pfadangabe zu libboost_thread.a:

    g++ spielesammlung.cpp -I /Library/boost_1_45_0/ -o thread.out /Library/boost_1_45_0/bin.v2/libs/thread/build/darwin-4.2.1/release/architecture-combined/link-static/threading-multi/libboost_thread.a  -lcurses
    

    vergleichsweise kurz nur zum boost-Verzeichnis:

    g++ spielesammlung.cpp -I /Library/boost_1_45_0/ -lcurses
    

    Es kommt immer wieder die Fehlermeldungen von oben - sowohl bei dem Beispiel als auch bei meinem Code 😞


  • Administrator

    1. Was für ein System hast du?
    2. Hast du die Boost Bibliothek gebaut?
    3. Wenn sie gebaut wurde, wo befinden sich die Bibliotheken? Hast du im Boost-Verzeichnis einen Unterordner /stage/lib/ ?
    4. Boost-Version ist 1.45, wenn ich das richtig sehe?
    5. Wenn der Unterordner existiert, sich darin die Bibliotheken befinden und du die oben erwähnte Version hast, dann würde ich das hier probieren:

    g++ spielesammlung.cpp -I /Library/boost_1_45_0/ -o thread.out /Library/boost_1_45_0/stage/lib/libboost-thread-gcc42-mt-1_45.a
    

    Überprüf bitte, ob dieses File ( libboost-thread-gcc42-mt-1_45.a ) auch existiert im Unterverzeichnis /stage/lib/ . Es könnte auch so ähnlich heissen, ich bin mir nicht sicher, ob ich mich an alle Konventionen gehalten habe der Namensgebung 🙂

    6. Verwende eine IDE!

    Grüssli



  • Auch auf dem Mac sollte Boost installiert werden. Das Installationsverzeichnis der Bibliotheken wird beim Linken mit der Compileroption -L <Pfad> angegeben. Die eigentlich Bibliothek wird mit -lboost_thread an den Linker übergeben. Außerdem müsste bei allen Compileschritten die Option -pthread angegeben werden, um den Compiler in den Threadmodus zu schalten. Der Aufruf sähe dann so aus:

    g++ -c spielesammlung.cpp -I<Pfad zu den Boostincludes> -pthread
    g++ -o sielesammlung spielesammlung.o -L<Pfad zu den Boost Libs> -lboost_thread -pthread
    

    Wenn du die Curses-Bibliothek benutzt fehlt natürlich noch das -lcurses.



  • @Dravere
    Ich hab Mac OS X in der neuesten Version. Die Boost Bibliothek hab ich nach dieser Anleitung gebaut. Die Bibliotheken sind in /stage/lib/ , allerdings befindet sich dort nicht libboost-thread-gcc42-mt-1_45.a , sondern libboost_thread.a . Boost hab in in der neusten Version 1.45. Der Aufruf

    g++ spielesammlung.cpp -I /Library/boost_1_45_0/ /Library/boost_1_45_0/stage/lib/libboost_thread.a  -lcurses
    

    bringt mich zu der gleichen Fehlermeldung wie oben.

    @manni66
    Auch deinen Vorschlag hab ich ausprobiert

    g++ -c spielesammlung.cpp -I/Library/boost_1_45_0/ -L/Library/boost_1_45_0/stage/lib/ -pthread -lcurses
    

    mit - mal wieder - gleichem Resultat.



  • Ein kleiner (vielleicht unpassender) Tip für die Zukunft,
    da ich vermute, dass bei boost builden etwas nicht so geklappt hat wie es sollte.

    Ich kann dir MacPorts (http://www.macports.org/) empfehlen.
    Wenn du das installiert hast, dann brauchst du einfach nur

    sudo port install boost
    

    eingeben und er macht alles automatisch.

    Da kannst du viele Libraries und Applikationen mit builden.



  • g0nz0 schrieb:

    @manni66
    Auch deinen Vorschlag hab ich ausprobiert

    g++ -c spielesammlung.cpp -I/Library/boost_1_45_0/ -L/Library/boost_1_45_0/stage/lib/ -pthread -lcurses
    

    mit - mal wieder - gleichem Resultat.

    Wenn du das genau so ausprobiert hast, kann es ja nicht funktionieren, denn es fehlt -lboost_thread.



  • hmmm... immer noch der gleiche Fehler.

    g++ -c spielesammlung.cpp -I/Library/boost_1_45_0/ -L/Library/boost_1_45_0/stage/lib/ -pthread -lboost_thread -lcurses
    In file included from spielesammlung.cpp:5:
    pong/pong.hpp: In member function ‘void pong::play()’:
    pong/pong.hpp:92: error: no matching function for call to ‘boost::thread::thread(<unresolved overloaded function type>)’
    /Library/boost_1_45_0/boost/thread/detail/thread.hpp:215: note: candidates are: boost::thread::thread(boost::detail::thread_move_tboost::thread)
    /Library/boost_1_45_0/boost/thread/detail/thread.hpp:201: note: boost::thread::thread(F, typename boost::disable_if<boost::is_convertible<T&, boost::detail::thread_move_t<T> >, boost::thread::dummy*>::type) [with F = void (pong::)()]
    /Library/boost_1_45_0/boost/thread/detail/thread.hpp:154: note: boost::thread::thread()
    /Library/boost_1_45_0/boost/thread/detail/thread.hpp:122: note: boost::thread::thread(boost::detail::thread_data_ptr)
    /Library/boost_1_45_0/boost/thread/detail/thread.hpp:113: note: boost::thread::thread(boost::thread&)
    pong/pong.hpp:94: error: no matching function for call to ‘boost::thread::thread(<unresolved overloaded function type>)’
    /Library/boost_1_45_0/boost/thread/detail/thread.hpp:215: note: candidates are: boost::thread::thread(boost::detail::thread_move_tboost::thread)
    /Library/boost_1_45_0/boost/thread/detail/thread.hpp:201: note: boost::thread::thread(F, typename boost::disable_if<boost::is_convertible<T&, boost::detail::thread_move_t<T> >, boost::thread::dummy
    >::type) [with F = void (pong::*)()]
    /Library/boost_1_45_0/boost/thread/detail/thread.hpp:154: note: boost::thread::thread()
    /Library/boost_1_45_0/boost/thread/detail/thread.hpp:122: note: boost::thread::thread(boost::detail::thread_data_ptr)
    /Library/boost_1_45_0/boost/thread/detail/thread.hpp:113: note: boost::thread::thread(boost::thread&)

    Das scheint doch wohl auch ein Compilerfehler zu sein und keiner vom Linker oder? Nichtsdestotrotz versuch ich grad mein Glück, indem ich boost einfach noch mal mit MacPorts builde. Sehe ich das richtig, dass boost damit in opt/local/ landet?



  • Das ist eine Compiler-Fehlermeldung, weil eventuell ball_moves und key_event nicht findet.

    Funktioniert denn das andere Beispiel?



  • Nein, ebenfalls altbekannte Linker-Fehlermeldung. Mich beschleicht auch so langsam das Gefühl, dass mit dem boost build irgendetwas nicht geklappt hat. MacPorts ist gerade am werkeln und mein Macbook kann ich gleich als Herdplatte verwenden. Ich hoffe damit wird es gleich funktionieren.

    //Edit
    Erfolgserlebnis! Dass ich das noch erleben darf. Das Codebeispiel kompiliert und lässt sich ausführen. Mein Programm allerdings produziert den gleichen Fehler. Das Problem ist imho das hier: ball_moves() und key_events() scheinen <unresolved overloaded function type> s zu sein. Was heißt das und wie behebe ich den Fehler?
    //Edit2:
    Jetzt blick ich gar nicht mehr durch... Folgendes im wesentlichen gleiche Codebeispiel funktioniert. Der einzige Unterschied ist, dass ball_movev() und key_events() nicht Methoden einer Klasse sondern Funktionen sind und dass die Threads in main() definiert werden.

    #include <iostream>
    #include <boost/thread.hpp>
    
    using namespace std;
    
    void ball_moves(){
      int a = 0;
      while(a<10){
        cout << a << endl;
        ++a;
      }
    }
    void key_events(){
      int a = 10;
      while(a<20){
        cout << a << endl;
        ++a;
      }
    } 
    
    int main(){
      boost::thread t1(ball_moves); 
      t1.join(); 
      boost::thread t2(key_events);
      t2.join();
      return 0;
    }
    

    Was mich zusätzlich irritiert ist die Tatsache, dass ich als Ausgabe fortlaufend die Zahlen 0 bis 19 bekomme. Ich dachte, das läuft gleichzeitig ab? Jetzt ist es doch wieder hintereinander!? Habe es noch auf die Spitze getrieben und in der ersten Funktion nach jeder Ausgabe die Wartefunktion des Beispielcodes implementiert. Resultat ist das gleiche, Ausgabe von 0 bis 19. Das heißt, die Schleifen laufen nichtmal synchron... 👎



  • Du musst den ersten Thread joinen, nachdem du den zweiten gestartet hast 😉
    Edit: Außerdem würde ich die Zugriffe auf cout synchronisieren.

    #include <iostream>
    #include <boost/thread.hpp>
    
    boost::mutex mutex;
    
    void ball_moves()
    {
        for(int a = 0; a < 10; ++a)
        {
            boost::lock_guard<boost::mutex> guard(mutex);
            std::cout << a << std::endl;
        }
    }
    
    void key_events()
    {
        for(int a = 10; a < 20; ++a)
        {
            boost::lock_guard<boost::mutex> guard(mutex);
            std::cout << a << std::endl;
        }
    }
    
    int main()
    {
       boost::thread t1(ball_moves);
       boost::thread t2(key_events);
       t1.join();
       t2.join();
    }
    

    Man könnte natürlich auch den lock-guard vor der Schleife erzeugen, dann würden halt alle Zahlen eines Threads nacheinander ausgegeben werden. (Weiters wäre es effizienter.)



  • @g0nz0:
    Wenn du Memberfunktionen als Thread ausführen willst, dann brauchst du einen "this" Zeiger dazu. boost::thread kann sich den nicht aus den Fingern saugen.
    -> boost::bind verwenden.

    #include <boost/bind.hpp>
    
    ...
    
    boost::thread t1(boost::bind(&klassenname::ball_moves, this));
    

    EDIT: hatte den boost::bind Aufruf vergessen 🙄



  • Vielen vielen lieben Dank euch allen. Es war eine schwere Geburt, aber ENDLICH läuft alles so wie ichs will 🙂


Anmelden zum Antworten