2016-12-22 2 views
4

Ich habe eine Worker-Thread, der ständig ausgeführt wird, erstellt & verwaltet über eine std::thread. Auf der obersten Ebene meines Worker-Threads habe ich einen try/catch-Block mit einer while-Schleife darin. Wenn eine Ausnahme auf die oberste Ebene des Faden leckt durch, fange ich es und speichert es in einem std::exception_ptr, das ein Mitglied der Klasse ist, die auch die nicht-statische Thread-Funktion besitzt:Ist std :: exception_ptr thread sicher?

// In class header (inside class definition) 
std::exception_ptr m_threadException; 

// In class CPP file 
void MyClass::MyThreadFunction() 
{ 
    try { 
     while (true) { 
      // Do thread stuff 
     } 
    } 
    catch (std::exception const& e) { 
     m_threadException = std::current_exception(); 
    } 
} 

Sobald das Gewinde stirbt aufgrund dieser Art von Ausnahme, meine Klasse (die auch hauptsächlich vom Hauptthread verwendet wird) weiß es noch nicht. Mein Plan war Thread Checkpoints an den Anfang aller Klasse Hauptfunktionen hinzufügen, etwa so:

void MyClass::SomethingMainThreadCalls() 
{ 
    if (m_threadException) { 
     std::rethrow_exception(m_threadException); 
     m_threadException = nullptr; // Somehow reset it back to null; not sure if this will work 
    } 

    // Do normal function stuff 
} 

Angenommen, dies ist auch eine gute Idee, es gibt eine mögliche Racebedingung zwischen wenn mein Haupt-Thread, wenn der exception_ptr prüft ist null (beim Aufruf von SomethingMainThreadCalls()) und wenn der Worker-Thread ihm zuweist. Ich habe keine Informationen gefunden (ich habe den C++ 11-Entwurf noch nicht überprüft), ob dies inhärent Thread-sicher ist (garantiert durch den Standard) oder ob ich in diesem Fall für die Thread-Synchronisierung verantwortlich bin.

Wenn Letzteres, ist std::atomic eine gute Idee, um es einfach zu halten? Beispiel:

std::atomic<std::exception_ptr> m_threadException; 

So ähnlich? Ich hoffe, dass die Antwort auf meine Frage auch einige gute Empfehlungen und Informationen zu Best Practice enthält. Danke im Voraus.

Antwort

3

Es gibt keine spezielle Aussage über exception_ptr hinsichtlich seiner Fadensicherheit in der Norm. Als solches bietet es die standardmäßige Standardgarantie: Zugriff auf separate Instanzen ist in Ordnung, Zugriff auf die gleiche Instanz ist nicht.

Ich würde vorschlagen, atomic<bool> anstelle von atomic<exception_ptr> zu verwenden, um den anderen Code wissen zu lassen, dass die exception_ptr gesetzt wurde.

  1. Sie setzen m_threadExceptionvor Setzen der Flagge
  2. Sie lesen m_threadExceptionnach eine Überprüfung des Flag
  3. Sie verwenden die entsprechenden Lade-/Speicher-Speicheraufträge einzustellen: Sie werden so lange in Ordnung sein/Überprüfen Sie die Flagge. Die Voreinstellungen sind in Ordnung
  4. Sie schreiben nur m_threadException genau einmal.
+0

Dies ist eine gute Idee. Es beseitigt auch die Notwendigkeit, den 'exception_ptr' auf null zu setzen. Laut cppreference.com gibt es keine dokumentierte Schnittstelle für 'exception_ptr', daher bin ich mir nicht einmal sicher, ob es einen Zuweisungsoperator für' nullptr' gibt. –

+3

@ void.pointer: Es hat eine "dokumentierte Schnittstelle". Es heißt [genau dort auf der Website] (http://en.cppreference.com/w/cpp/error/exception_ptr): "' std :: exception_ptr' erfüllt die Anforderungen von [NullablePointer] (http: // en. cppreference.com/w/cpp/concept/NullablePointer)."Es sagt sogar, was die Standard- und Kopierkonstruktoren tun. Sowie Vergleichsoperatoren. –

+0

Entschuldigung, Tunnel Vision. Ich erwartete eine tatsächliche Interface-Spezifikation auf dieser Seite, wie cppreference.com normalerweise für andere Klassen-Typen. Danke." –

2

Der Standard gibt nicht an, was die Implementierung von std::exception_ptr ist, so dass die Thread-Sicherheit von std::exception_ptr auch nicht spezifiziert ist.

wickeln Sie einfach den Ausnahmezeiger mit einer Sperre und der Code wird in Ordnung sein.