2010-12-22 3 views
13

In diesen Tagen lese ich die pdf Designing MT programs. Es wird erläutert, dass der Benutzer detach() für ein Objekt der Klasse std::thread in C++ 0x explizit aufrufen muss, bevor das Objekt den Gültigkeitsbereich verlässt. Wenn Sie es nicht anrufen, wird std::terminate() aufgerufen und die Anwendung wird absterben.Thread Destruktoren in C++ 0x vs Boost

Normalerweise verwende ich boost::thread zum Threading in C++. Korrigieren Sie mich, wenn ich falsch liege, aber ein Objekt löst sich automatisch, wenn es den Rahmen verlässt.

scheint mir, dass der Boost-Ansatz ein RAII-Prinzip folgen und die Std nicht.

Wissen Sie, ob es einen bestimmten Grund dafür gibt?

Antwort

16

Dies ist in der Tat wahr, und diese Wahl wird in N3225 auf einer Notiz in Bezug auf std::thread destructor erklärt:

Wenn joinable() dann terminate(), da ansonsten keine Auswirkungen. [Hinweis: entweder implizit Abnehmen oder ein joinable() Faden in seinem destructor Beitritt nur in schwierigen zu debuggen Korrektheit (für detach) oder Leistung führen könnte (für join) Bugs auftreten, wenn eine Ausnahme angehoben. So muss der Programmierer sicherstellen, dass der Destruktor niemals ausgeführt wird, während der Thread noch verbindbar ist. -Ende note]

Offenbar ging der Ausschuss für das kleinere von zwei Übeln.


EDIT Ich habe gerade this interesting paper weshalb die ursprüngliche Formulierung erklärt:

Wenn joinable() dann detach(), da ansonsten keine Auswirkungen.

wurde für den zuvor zitierten geändert.

+1

Warum nicht ein join_on_destruction- oder detach_on_destruction-Flag im Konstruktor oder eine andere Möglichkeit, das Verhalten explizit anzugeben. – Puppy

+0

Es gibt ein interessantes Papier [hier] (http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2008/n2802.html) – icecrime

+1

Hallo IceCrime. Danke für das Papier. Im Grunde ist das Töten der Anwendung der offensichtlichste Weg, um eine Flagge über Fehler in Threads zu heben. Interessant und wirklich "defensiv" würde ich sagen. :) –

3

Hier ist eine Möglichkeit, RAII-Threads zu implementieren.

#include <memory> 
#include <thread> 

void run() { /* thread runs here */ } 

struct ThreadGuard 
{ 
    operator()(std::thread* thread) const 
    { 
     if (thread->joinable()) 
      thread->join(); // this is safe, but it blocks when scoped_thread goes out of scope 
     //thread->detach(); // this is unsafe, check twice you know what you are doing 
     delete thread; 
    } 
} 

auto scoped_thread = std::unique_ptr<std::thread, ThreadGuard>(new std::thread(&run), ThreadGuard()); 

Wenn Sie diese verwenden möchten, einen Faden zu lösen, read this first.