Ich konnte leider nie einen Weg finden, dies zu tun.
Ohne eine Art Thread-Init-Hook scheint es einfach keinen Weg zu geben, an diesen Zeiger zu gelangen (abgesehen von ASM-Hacks, die plattformabhängig wären).
Wenn Sie Thread-lokale Variablen wollen, die keine Thread-lokalen sind, warum verwenden Sie stattdessen nicht globale Variablen?
Wichtige Klarstellung!
Ich schlage nicht vor, dass Sie eine einzelne globale verwenden, um eine Thread-lokale Variable zu ersetzen. Ich schlage vor, ein einzelnes globales Array zu verwenden oder eine andere geeignete Sammlung von Werten, um eine Thread-lokale Variable zu ersetzen.
Sie müssen natürlich für eine Synchronisation sorgen, aber da Sie einen in Thread A geänderten Wert für Thread B offenlegen möchten, führt kein Weg daran vorbei.
Aktualisierung:
Die GCC-Dokumentation zu __thread
sagt:
Wenn der address-of-Operator auf eine Thread-lokale Variable angewendet wird, wird er zur Laufzeit ausgewertet und gibt die Adresse der Instanz dieser Variablen im aktuellen Thread zurück. Eine so erhaltene Adresse kann von jedem Thread verwendet werden. Wenn ein Thread beendet wird, werden alle Zeiger auf Thread-lokale Variablen in diesem Thread ungültig.
Wenn Sie darauf bestehen, diesen Weg zu gehen, stelle ich mir daher vor, dass es möglich ist, die Adresse einer lokalen Thread-Variablen aus dem Thread zu erhalten, zu dem sie gehört, kurz nachdem der Thread erzeugt wurde. Sie könnten dann einen Zeiger auf diesen Speicherort in einer Zuordnung speichern (Thread-ID => Zeiger) und andere Threads auf diese Weise auf die Variable zugreifen lassen. Dies setzt voraus, dass Sie den Code für den erstellten Thread besitzen.
Wenn Sie wirklich abenteuerlustig sind, können Sie versuchen, Informationen auf ___tls_get_addr
auszugraben (beginnen Sie mit diesem PDF, das mit den oben genannten GCC-Dokumenten verlinkt ist). Aber dieser Ansatz ist so hochgradig Compiler- und plattformspezifisch und es fehlt ihm so an Dokumentation, dass er in jedem Kopf Alarm schlagen sollte.
Ich suche nach der gleichen Sache. Wie ich sehe, hat niemand Ihre Frage beantwortet, nachdem ich das Internet auf alle Arten durchsucht hatte, kam ich zu den folgenden Informationen:Angenommen, für gcc unter Linux (Ubuntu) zu kompilieren und -m64, das Segmentregister gs, zu verwenden enthält den Wert 0. Der verborgene Teil des Segments (der die lineare Adresse enthält) zeigt auf den Thread-spezifischen lokalen Bereich. Dieser Bereich enthält an dieser Adresse die Adresse dieser Adresse (64 Bit). An niedrigeren Adressen werden alle lokalen Thread-Variablen gespeichert. Diese Adresse ist die native_handle()
.Um also auf lokale Daten eines Threads zuzugreifen, sollten Sie dies über diesen Zeiger tun.
Mit anderen Worten:(char*)&variable-(char*)myThread.native_handle()+(char*)theOtherThread.native_handle()
Der Code, der das Obige unter der Annahme von g++, linux, pthreads demonstriert, ist:
#include <iostream>
#include <thread>
#include <sstream>
thread_local int B=0x11111111,A=0x22222222;
bool shouldContinue=false;
void code(){
while(!shouldContinue);
std::stringstream ss;
ss<<" A:"<<A<<" B:"<<B<<std::endl;
std::cout<<ss.str();
}
//#define ot(th,variable)
//(*( (char*)&variable-(char*)(pthread_self())+(char*)(th.native_handle()) ))
int& ot(std::thread& th,int& v){
auto p=pthread_self();
intptr_t d=(intptr_t)&v-(intptr_t)p;
return *(int*)((char*)th.native_handle()+d);
}
int main(int argc, char **argv)
{
std::thread th1(code),th2(code),th3(code),th4(code);
ot(th1,A)=100;ot(th1,B)=110;
ot(th2,A)=200;ot(th2,B)=210;
ot(th3,A)=300;ot(th3,B)=310;
ot(th4,A)=400;ot(th4,B)=410;
shouldContinue=true;
th1.join();
th2.join();
th3.join();
th4.join();
return 0;
}