La conseguenza principale è che il thread potrebbe iniziare a funzionare (e usare il puntatore) prima che il costruttore sia completato, quindi l'oggetto potrebbe non essere in uno stato definito/utilizzabile. Allo stesso modo, a seconda di come il thread viene interrotto, potrebbe continuare a essere eseguito dopo l'avvio del distruttore e quindi l'oggetto potrebbe non essere in uno stato utilizzabile.
Questo è particolarmente problematico se la classe è una classe base, poiché il costruttore della classe derivata non inizierà nemmeno l'esecuzione fino a quando non sarà terminato il costruttore e il distruttore della classe derivata avrà completato prima dell'avvio del proprio. Inoltre, le chiamate alle funzioni virtuali non fanno ciò che si potrebbe pensare prima che le classi derivate siano costruite e dopo che sono state distrutte: le chiamate virtuali "ignorano" le classi la cui parte dell'oggetto non esiste.
Esempio:
struct BaseThread {
MyThread() {
pthread_create(thread, attr, pthread_fn, static_cast<void*>(this));
}
virtual ~MyThread() {
maybe stop thread somehow, reap it;
}
virtual void id() { std::cout << "base\n"; }
};
struct DerivedThread : BaseThread {
virtual void id() { std::cout << "derived\n"; }
};
void* thread_fn(void* input) {
(static_cast<BaseThread*>(input))->id();
return 0;
}
Ora, se si crea un DerivedThread, si tratta di una migliore una gara tra il filo che costruisce e il nuovo thread, per determinare quale versione di id()
viene chiamato. Potrebbe succedere che qualcosa di peggio possa succedere, avresti bisogno di guardare abbastanza da vicino la tua API e compilatore di threading.
Il modo usuale di non doversi preoccupare di questo è solo per dare alla classe thread una funzione start()
, che l'utente chiama dopo averla costruita.
fonte
2010-03-25 15:47:52
@gilbertc: se B deriva da A, anche se si avvia il thread alla fine del costruttore di A, tutto da B (vtable, variabili membro, codice costruttore) non verrà inizializzato/eseguito. Potrebbe essere un brutto bug di concorrenza? A prima vista, direi di sì, perché l'oggetto cambierà nel thread di costruzione, mentre potrebbe essere utilizzato nel thread appena creato. – paercebal