2010-07-01 14 views
6

Implementierung habe ich ein kleines Wrapper, der zentralisieren, was Threads relativ ist:„rein virtuelle Methode namens“, wenn ein boost :: Thread Wrapper-Schnittstelle

class Thread { 
protected: 
    boost::thread *m_thread; 

    virtual void work() = 0; 

    void do_work() { 
     work(); 
    } 

public: 
    Thread() : m_thread(NULL) {} 
    virtual ~Thread() { 
     catch_up(); 
     delete m_thread; 
    } 

    inline void catch_up() { 
     if(m_thread != NULL) { 
      m_thread->join(); 
     } 
    } 

    void run() { 
     m_thread = new boost::thread(boost::bind(&Thread::do_work, boost::ref(*this))); 
    } 
}; 

Als ich es implementieren, sagen mit den folgenden:

class A : public Thread { 
    void work() {} 
}; 

An:

A a; a.run(); 

bekam ich eine Laufzeit Beendigung mit einer hübschen „rein virtuellen Methode namens“ displ ayed. Ich denke, es ist das boost :: bind-Argument, aber ich weiß nicht, wie ich sagen soll "Benutze virtuelle reine Implementierung" ...

Danke im Voraus.

Grüße,

Herr Mystère

Antwort

6

Ihr Absturz geschieht nur, wenn das Programm sofort beendet: es nennt destructor Klasse A ist, welche beendet und ruft Thema Destruktor vor die neu gestartete Thread eine Chance hatte geplant werden. Der Thread ruft dann Ihre virtuelle Funktion auf, aber Klasse A existiert nicht mehr. Daher versucht Thread, do_work() aufzurufen, was die reine virtuelle Arbeit() aufruft. Hier ist das Programm mit zusätzlichen Ausgaben:

run() started 
run() ended 
~A() started 
~A() ended 
~Thread() started 
catch_up() started 
do_work() started 
pure virtual method called 

Norm-weise, ich denke, das ist nicht definiertes Verhalten ist, weil die Lebensdauer des Objekts bereits beendet ist (Destruktoraufrufs begann), wenn ein Verweis darauf (boost::ref(*this)) verwendet do_work zu nennen () aus dem Thread.

Lösung: lassen Sie Ihren Thread ausführen, bevor Sie Ihr Objekt zerstören:

A a; a.run(); 
a.catch_up(); 

Oder, wie Boost.Thread Dokumentation sagt, "the user of Boost.Thread must ensure that the referred-to object outlives the newly-created thread of execution."

+0

Nun, das war einfach ... Danke, du hast es deutlich gemacht. Aber jetzt habe ich ein größeres Problem (zufällige Booleans anscheinend ...), und ich denke, es wird viel schwieriger zu debuggen sein. Ich hätte meinen "Joker" einfach nicht dafür benutzen sollen, sonst werde ich bedürftig aussehen ^^ –

1

Ich bin auf einem Bein hier geht, aber ich vermute, dass das Problem mit dem Thema destructor ist:

virtual ~Thread() { 
    catch_up(); 
    delete m_thread; 
} 

Wenn der Faden nicht hat noch nicht gestartet, ruft catch_up() im Destruktor den Boost-Thread mit der Thread-V-Tabelle anstelle von A, wie in C++ an der Stelle des Destruktors die V-Tabelle entspricht den Bereich des Typs des Destruktors, nicht die meisten abgeleiteten V-Tabelle.

+0

ich neu denken ordnet den Thread-Handle, nachdem es richtig zu schaffen? Das Einchecken in catch_up(), wenn m_thread gleich NULL ist, genügt also, um es zu schützen, falls der Destruktor schneller ist als die Erstellung des Threads. –

+0

Ich beziehe mich auf den Destruktor von Thread, nicht auf den Destruktor von boost :: thread. – MSN

+0

Ich weiß, ich habe darüber auch gesprochen. Aber jetzt, da ich es verstehe, denke ich, hast du es auch darauf hingewiesen, Entschuldigung dafür, dass du es falsch verstanden hast;) –

Verwandte Themen