2010-07-01 18 views
6

Mam małe opakowanie, które centralizacji, co w stosunku do wątków:„czysta wirtualna metoda nazywa się” przy wdrażaniu Boost :: wątek interfejs otoki

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))); 
    } 
}; 

Kiedy wdrożyć go, powiedzieć, co następuje:

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

w:

A a; a.run(); 

dostałem wypowiedzenie wykonania z dość „czystego metoda wirtualna nazwie” displ ayed. Myślę, że to argument boost :: bind, ale nie wiem, jak powiedzieć "Użyj wirtualnej czystej implementacji" ...

Dzięki temu.

Pozdrawiam,

Mister Mystere

Odpowiedz

6

Twój awarii zdarza się tylko gdy program kończy działanie natychmiast: to nazywa klasa A za destruktor które wykończenia i wywołuje destruktor wątku przed nowo rozpoczęty wątek miał szansę być zaplanowane. Wątek następnie wywołuje twoją funkcję wirtualną, ale klasa A już nie istnieje, więc próbuje wywołać wątek do_work(), który wywołuje czystą pracę wirtualną(). Oto program z dodatkowymi wyjściami:

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

Standard-mądry, myślę, że to jest niezdefiniowane zachowanie ponieważ czas istnienia obiektu został już zakończony (wywołanie destruktora zaczął), gdy odniesienie do niego (boost::ref(*this)) użyto zadzwonić do_work () z wątku.

Rozwiązanie: niech wątek wykonać przed zniszczeniu swój obiekt:

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

Lub, jak mówi dokumentacja boost.thread, "the user of Boost.Thread must ensure that the referred-to object outlives the newly-created thread of execution."

+0

Cóż, to było proste ... Dzięki, wyjaśniłeś. Ale teraz mam większy problem (przypadkowo booleans najwyraźniej ...) i myślę, że będzie trudniej debugować. Po prostu nie powinienem używać mojego "jokera" tutaj, w przeciwnym razie będę wyglądał na potrzebującego ^^ " –

1

Idę w opałach tutaj, ale podejrzewam, że problem jest z destructor Temat:

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

Jeśli nić nie ma jeszcze rozpoczęte, wywołanie catch_up() w destruktorze rozpocznie wątek doładowania za pomocą vtable Thread zamiast A, tak jak w C++ w punkcie destruktora vtable pasuje do zakresu typu destruktora, a nie do najbardziej pochodnego vtable.

+0

myślę nowy wątek alokuje uchwyt po utworzeniu go prawda? Zatem sprawdzenie catch_up(), jeśli m_thread jest równy NULL, wystarczy, aby go zabezpieczyć na wypadek, gdyby destruktor był szybszy niż tworzenie wątku. –

+0

Mam na myśli destruktor wątku, a nie boost :: thread's destructor. – MSN

+0

Wiem, o tym też mówiłem. Ale teraz, jak rozumiem, myślę, że ty też to wskazałeś, przepraszam, że źle zrozumiałem, moje złe;) –

Powiązane problemy