gcc 4.7 auf linux pthreads - nicht-triviale thread_local Workaround mit __thread (keine boost)

8

In C ++ 11 können Sie ein nicht-triviales Objekt mit thread_local speichern:

%Vor%

Leider wurde diese Funktion noch nicht in gcc implementiert (ab 4.7).

gcc erlaubt Ihnen lokale Thread-Variablen, aber nur mit trivialen Typen.

Ich suche nach einem Workaround:

Hier ist was ich bisher habe:

%Vor%

Wofür ich Hilfe brauche ist placement_delete_x (& amp; x_storage) beim Beenden des aktuellen Threads. Gibt es einen Mechanismus in Pthreads und / oder Linux, den ich dafür verwenden kann? Ich würde einen Funktionszeiger und einen Parameter zu irgendeiner Art pthread Reinigungsstapel hinzufügen müssen?

Aktualisierung:

Ich denke, pthread_cleanup_push könnte das sein, was ich will:

Ссылка

Wird dies den Bereinigungshandler unter den richtigen Umständen für diese Verwendung aufrufen?

Update 2:

Es sieht so aus, als ob boost::thread_specific_ptr schließlich pthread_key_create mit dem Parameter destructor aufruft und nicht pthread_cleanup_push - um seine tls-Bereinigungsfunktion aufzurufen:

Ссылка

Es ist unklar, was der Unterschied zwischen diesen beiden Methoden ist, wenn überhaupt. ?

    
Andrew Tomazos 21.08.2012, 06:51
quelle

2 Antworten

2

Wie Mike sagt pthread_cleanup_push ist nicht angemessen. Der richtige Weg ist die Verwendung von pthread_key_create .

Ich habe ein kleines Demo-Programm implementiert, um zu zeigen, wie es geht. Wir implementieren ein Makro thread_local , das Sie so verwenden:

Mit der echten C ++ 11-Funktion wäre es:

%Vor%

Damit ist es:

%Vor%

Der Unterschied zwischen diesem Wert und boost :: thread_specifc_ptr ist, dass es keine dynamische Speicherzuweisung gibt. Alles wird mit __thread duration gespeichert. Es ist auch deutlich leichter, aber es ist gcc / linux-spezifisch.

Übersicht:

  1. Wir haben std::aligned_storage verwendet, um Platz für __thread für die Variable
  2. zu schaffen
  3. Beim ersten Eintrag eines gegebenen Threads verwenden wir placement new, um die Variable im Speicher
  4. zu konstruieren
  5. Wir weisen auch __thread einen verknüpften Listeneintrag dem Placement-Lösch-Aufruf zu
  6. zu
  7. Wir verwenden pthread_setspecific , um jeden Thread-Listenkopf
  8. zu verfolgen
  9. Die an pthread_key_create übergebene Funktion durchläuft die Liste, die das Placement aufruft, wenn der Thread beendet wird.

...

%Vor%

Anmerkungen:

  1. Sie müssen jedem Aufruf von pthread_ * eine Fehlerprüfung hinzufügen. Ich habe es nur zur Ausstellung entfernt.
  2. Es verwendet __thread , eine GNU-Erweiterung
  3. Es verwendet eine -Ausdruckanweisung , um die zusätzlichen __thread-Variablennamen außerhalb des übergeordneten Bereichs zu behalten. Dies ist auch eine GNU-Erweiterung.
Andrew Tomazos 21.08.2012, 11:30
quelle
3

pthread_key_create und Freunde sind das, was Sie Thread-spezifische Variablen von Typen mit Destruktoren implementieren möchten. In der Regel müssen Sie jedoch den gesamten Prozess zum Erstellen und Löschen der Variablen verwalten, und ich bin mir nicht sicher, ob Sie sie in Verbindung mit __thread verwenden könnten.

pthread_cleanup_push ist nicht geeignet. Es ist vorgesehen, dass eine Ressource freigegeben wird, wenn der Thread während eines (kurzen) Codeblocks endet, der diese Ressource verwendet. Wie in der Dokumentation beschrieben, auf die Sie verlinken, muss mit einem pthread_cleanup_pop auf derselben Ebene dieser Funktion verglichen werden, und der Handler wird nicht aufgerufen, wenn der Thread von seiner Hauptfunktion zurückkehrt. Das bedeutet, dass Sie sie nicht verwenden können, wenn die Thread-lokale Variable zwischen Aufrufen der Funktion beibehalten werden soll.

Für diejenigen, die kein Verbot für Bibliotheken von Drittanbietern haben, Boost bietet eine praktische, portable Möglichkeit, Thread-lokalen Speicher zu verwalten.

    
Mike Seymour 21.08.2012 09:55
quelle