Sayangnya saya tidak pernah dapat menemukan cara untuk melakukan ini.
Tanpa semacam kait init utas, tampaknya tidak ada cara untuk mendapatkan penunjuk itu (kurang dari peretasan ASM yang bergantung pada platform).
Jika Anda ingin meng-thread variabel lokal yang bukan thread lokal, mengapa Anda tidak menggunakan variabel global saja?
Klarifikasi penting!
Saya tidak menyarankan Anda menggunakan satu global untuk mengganti variabel thread-local. Saya menyarankan untuk menggunakan array global tunggal atau kumpulan nilai lain yang sesuai untuk menggantikan satu variabel thread-local.
Anda tentu saja harus menyediakan sinkronisasi, tetapi karena Anda ingin mengekspos nilai yang dimodifikasi di utas A ke utas B, tidak ada jalan lain.
Perbarui:
Dokumentasi GCC di __thread
mengatakan:
Ketika alamat-operator diterapkan ke variabel thread-local, itu dievaluasi pada saat run-time dan mengembalikan alamat dari instance thread saat ini dari variabel itu. Alamat yang diperoleh dapat digunakan oleh utas apa pun. Saat utas berakhir, penunjuk apa pun ke variabel lokal utas di utas itu menjadi tidak valid.
Oleh karena itu, jika Anda bersikeras untuk pergi dengan cara ini, saya membayangkan mungkin untuk mendapatkan alamat variabel lokal utas dari utas miliknya, tepat setelah utas itu muncul. Anda kemudian dapat menyimpan penunjuk ke lokasi memori itu ke peta (utas id => penunjuk), dan biarkan utas lain mengakses variabel dengan cara ini. Ini mengasumsikan bahwa Anda memiliki kode untuk utas yang dihasilkan.
Jika Anda benar-benar berjiwa petualang, Anda dapat mencoba menggali informasi di ___tls_get_addr
(mulai dari PDF ini yang ditautkan oleh dokumen GCC yang disebutkan di atas). Tetapi pendekatan ini sangat kompiler dan spesifik platform dan sangat kurang dalam dokumentasi yang seharusnya menyebabkan alarm berbunyi di kepala siapa pun.
Saya mencari hal yang sama. Seperti yang saya lihat, tidak ada yang menjawab pertanyaan Anda setelah mencari di web dengan segala cara, saya sampai pada informasi selanjutnya:seandainya mengkompilasi untuk gcc di linux (ubuntu) dan menggunakan -m64, register segmen gs memegang nilai 0. Bagian tersembunyi dari segmen (memegang alamat linier) menunjuk ke area lokal spesifik utas. Area itu berisi alamat alamat itu (64 bit). Di alamat yang lebih rendah disimpan semua variabel lokal utas. Alamat itu adalah native_handle()
.Jadi untuk mengakses data lokal utas, Anda harus melakukannya melalui penunjuk itu.
Dengan kata lain:(char*)&variable-(char*)myThread.native_handle()+(char*)theOtherThread.native_handle()
Kode yang menunjukkan anggapan di atas g++,linux,pthreads adalah:
#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;
}