2009-11-02 26 views
9

Sto riscontrando un problema in cui una chiamata al thread di boost-> entra in un distruttore porta a un deadlock. Non capisco perché, e non sono troppo entusiasta di mantenere il codice che funziona (e non capisco perché lo fa) nel progetto.Partecipare a un'istanza boost :: thread nel distruttore

dichiarazione Classe (ho messo a nudo il metodo run() del try/catch per brevità: in base alla documentazione filo spinta, il risultato dovrebbe essere lo stesso con o senza di essa):

class B 
{ 
public: 
    void operator()(){run();} 
    void run(); 
    void shutdown(); 
    ~B(); 
    B(); 
    boost::thread *thr; 
    bool shutdown_requested; 
}; 

void B::shutdown() 
{ 
    shutdown_requested = true; 

    if (thr != NULL) 
    { 
     thr->interrupt(); 
     thr->join(); // deadlock occurs here! 
     delete thr; 
     thr = NULL; 
    } 
} 

B::~B() 
{ 
    shutdown(); 
} 

B::B() 
{ 
    thr = new boost::thread(boost::ref(*this)); 
} 

void B::run() 
{ 
    while (!shutdown_requested) 
    { 
     boost::xtime xt; 
     boost::xtime_get(&xt, boost::TIME_UTC); 
     xt.sec += 30; 
     boost::this_thread::sleep(xt); 
    } 
} 

Snippet che non funziona:

int main() 
{ 
    B *b = new B; 

    Sleep(5000); 
    printf("deleting \n");fflush(stdout); 
// b->shutdown(); 
    delete b; 
    printf("done\n");fflush(stdout); 

    return 0; 
} 

frammento che funziona:

int main() 
{ 
    B *b = new B; 

    Sleep(5000); 
    printf("deleting \n");fflush(stdout); 
    b->shutdown(); 
    delete b; 
    printf("done\n");fflush(stdout); 

    return 0; 
} 

penso che il ragione di questo comportamento ha qualcosa a che fare con questo frammento della documentazione spinta:

l'utente del Boost.Thread deve assicurare che il cui-di opporsi sopravvive il thread appena creato di esecuzione.

Ma non capisco veramente perché il deadlock - unendo il thread non chiamerebbe il distruttore su B e l'oggetto stesso non viene eliminato quando il metodo run() deve uscire.

+1

Buona domanda e ben chiesta. Non conosco una risposta, ma hai dato un'occhiata all'implementazione di boost :: thread? O hai provato a debuggarlo? Forse questo ti dà un suggerimento. Osservando il codice di esempio, direi che dovrebbe funzionare bene. – MP24

+0

Grazie, ho trovato il problema entrando nel debugger. Era correlato al codice di rilevamento perdite. – laura

risposta

4

Ho riscontrato il problema: si riduce a un programmatore troppo zelante.

Avevo originariamente compilato il mio progetto utilizzando DUMA (http://sourceforge.net/projects/duma/) per verificare se la mia implementazione del modulo corrente era senza perdite. Sfortunatamente, il mio sandbox di prova aveva anche le impostazioni di duma, cosa che non avevo realizzato fino a quando non ho passato il codice in un debugger.

Dopo aver rimosso tutto il rilevamento perdite di memoria, tutto funziona come previsto.

+0

Si noti che è possibile accettare la propria risposta per contrassegnare la domanda come risposta. – MP24

+0

Solo dopo due giorni sfortunatamente. Grazie ancora per l'aiuto – laura