C++11: Nichttriviale Thread-Lokale Statische Variable?
Habe ich eine Klasse X:
class X { ... }
Ich dies tun möchten:
void f()
{
thread_local static X x = ...;
...
}
(eigentlich bin ich mit gcc, so dass Schlüsselwort "__thread")
aber ich kann nicht, weil Sie nur triviale thread_locals.
Was ist der beste work-around dafür?
Wenn ich es so machen:
void f()
{
thread_local static X* p = 0;
if (!p)
p = new X(...);
X& x = *p;
...
}
dann:
- der Destruktor wird nicht aufgerufen, wenn der thread beendet
- unnötige dynamische Speicherzuweisung.
Update:
Hier ist was ich habe, so weit:
#include <iostream>
#include <type_traits>
using namespace std;
class X { public: X() { cout << "X::X()" << endl; }; ~X() { cout << "X::~X()" << endl; } };
void f()
{
static __thread bool x_allocated = false;
static __thread aligned_storage<sizeof(X),
alignment_of<X>::value>::type x_storage;
if (!x_allocated)
{
new (&x_storage) X;
x_allocated = true;
//add thread cleanup that calls destructor
}
X& x = *((X*) &x_storage);
}
int main()
{
f();
}
Dieser behebt das dynamic memory allocation problem. Ich brauche nur hinzuzufügen, der thread cleanup-handler. Gibt es dafür einen Mechanismus mit pthreads?
- Warum können Sie nur triviale thread-einheimischen? Par-standard?
- Ich dachte so? GCC scheint nicht, es zu mögen.
- Ich glaube nicht, dass der standard solche Beschränkungen, und GCC nicht implementiert C++11 thread local storage.
- gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Thread_002dLocal.html
- Das ist eine gcc-Erweiterung, nicht C++11
thread_local
. Siehe hier. Also, wenn es nicht umgesetzt wird, werden Sie nicht haben, das problem der Trivialität. - Ja, ich sehe jetzt. Was ist der beste workaround in der Zwischenzeit?
- sorry, wenn ich wusste, ich hätte eine Antwort 🙂
- stackoverflow.com/questions/12049684/...
- Ich glaube, ich habe einen Fall, wo thread_local nicht-POD-Objekt ist nicht initialisiert, in VS 2015 bei der Verwendung des nativen Bibliothek aus .NET. Manchmal.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Norm beschreibt
thread_local
als storage-Planer wie die anderen (static
,extern
etc.) in §7.1.1. Es gibt keine Beschränkung auf "einfache" Datentypen in jeder Bedeutung dieses Wortes.Das problem wird kurz diskutiert, in einem pre-C++11-Diskussionspapier N2147 (siehe Abschnitt "Thread-Variable Dynamische Initialisierung"). Das schließt eine Beschreibung der wichtigsten Probleme in der korrekten Umsetzung. Offenbar ist die GCC-Implementierung (
static __thread
) noch nicht gelöst sind diese Probleme noch (das ist konsistent mit der Tatsache, dass GCC nicht offiziell unterstützt C++11thread_local
).Eine alternative ist
boost::thread_specfic_ptr<>
erwähnt in diesem früheren post und beschrieben hier.Andere alternative ist die Verwendung eines
std::thread
Objekt zu implementieren, der thread und sicherzustellen, dass jede Instanz verwaltet seine eigene Kopie der Variablen, eventuell eingewickelt in eineunique_ptr
.thread_local
und__thread
sind in der Tat nicht das gleiche. Der wesentliche Unterschied zwischen Ihnen ist genau die, die Sie gestolpert -thread_local
ermöglicht die variable nicht-POD. Leider hat dies auch Auswirkungen auf die Leistung. Sehen diese Frage für mehr details über die Auswirkungen auf die Leistung.