Purtroppo non sono mai riuscito a trovare un modo per farlo.
Senza un qualche tipo di thread init hook non sembra proprio esserci un modo per arrivare a quel puntatore (a parte gli hack di ASM che sarebbero dipendenti dalla piattaforma).
Se vuoi variabili locali di thread che non siano locali di thread, perché non usi invece variabili globali?
Chiarimento importante!
Non sto suggerendo di utilizzare un singolo globale per sostituire una variabile locale del thread. Sto suggerendo di utilizzare un singolo array globale o altra raccolta di valori adatta per sostituire una variabile locale del thread.
Ovviamente dovrai fornire la sincronizzazione, ma dal momento che vuoi esporre un valore modificato nel thread A al thread B non c'è modo di aggirarlo.
Aggiornamento:
La documentazione GCC su __thread
dice:
Quando l'operatore address-of viene applicato a una variabile locale del thread, viene valutato in fase di esecuzione e restituisce l'indirizzo dell'istanza del thread corrente di quella variabile. Un indirizzo così ottenuto può essere utilizzato da qualsiasi thread. Quando un thread termina, qualsiasi puntatore a variabili locali del thread in quel thread diventa non valido.
Pertanto, se insisti ad andare in questo modo, immagino sia possibile ottenere l'indirizzo di una variabile locale del thread dal thread a cui appartiene, subito dopo che il thread è stato generato. È quindi possibile memorizzare un puntatore a quella posizione di memoria in una mappa (id thread => puntatore) e consentire ad altri thread di accedere alla variabile in questo modo. Ciò presuppone che tu possieda il codice per il thread generato.
Se sei davvero avventuroso, potresti provare a scovare informazioni su ___tls_get_addr
(inizia da questo PDF a cui è collegato dai suddetti documenti GCC). Ma questo approccio è così altamente specifico per compilatore e piattaforma e così privo di documentazione che dovrebbe far scattare allarmi nella testa di chiunque.
Sto cercando la stessa cosa. Come vedo nessuno ha risposto alla tua domanda dopo aver cercato nel web in tutti i modi sono arrivato alle seguenti informazioni:supponendo di compilare per gcc su linux (ubuntu) e usando -m64, il registro di segmento gs contiene il valore 0. La parte nascosta del segmento (contenente l'indirizzo lineare) punta all'area locale specifica del thread. Quell'area contiene a quell'indirizzo l'indirizzo di quell'indirizzo (64 bit). Agli indirizzi inferiori sono memorizzate tutte le variabili locali del thread. Quell'indirizzo è il native_handle()
.Quindi, per accedere ai dati locali di un thread, dovresti farlo tramite quel puntatore.
In altre parole:(char*)&variable-(char*)myThread.native_handle()+(char*)theOtherThread.native_handle()
Il codice che dimostra quanto sopra supponendo g++,linux,pthreads è:
#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;
}