残念ながら、これを行う方法を見つけることができませんでした.
ある種のスレッド初期化フックがなければ、そのポインターを取得する方法がないように見えます (プラットフォームに依存する ASM ハックを除けば)。
スレッド ローカルではないスレッド ローカル変数が必要な場合は、代わりにグローバル変数を使用してみませんか?
重要な説明!
単一のグローバルを使用してスレッドローカル変数を置き換えることを提案しているわけではありません。単一のグローバル 配列 を使用することをお勧めします または他の適切な値のコレクションで、1 つのスレッドローカル変数を置き換えます。
もちろん、同期を提供する必要がありますが、スレッド A で変更された値をスレッド B に公開したいので、それを回避することはできません。
更新:
__thread
に関する GCC ドキュメント 言います:
address-of 演算子がスレッド ローカル変数に適用されると、実行時に評価され、その変数の現在のスレッドのインスタンスのアドレスが返されます。取得したアドレスは、どのスレッドでも使用できます。スレッドが終了すると、そのスレッド内のスレッドローカル変数へのポインタはすべて無効になります。
したがって、この方法を主張する場合は、スレッドが生成された直後に、それが属するスレッドからスレッドローカル変数のアドレスを取得できると思います。次に、そのメモリ位置へのポインターをマップ (スレッド ID => ポインター) に格納し、他のスレッドがこの方法で変数にアクセスできるようにします。これは、生成されたスレッドのコードを所有していることを前提としています。
あなたが本当に冒険好きなら、___tls_get_addr
の情報を掘り下げてみてください。 (前述の GCC ドキュメントからリンクされているこの PDF から始めます)。しかし、このアプローチは非常にコンパイラとプラットフォームに固有であり、ドキュメントが不足しているため、誰かの頭の中でアラームが鳴るはずです.
私は同じことを探しています.あらゆる方法でウェブを検索した後、誰もあなたの質問に答えていないことがわかりました.次の情報にたどり着きました.値 0 を保持します。セグメントの非表示部分 (線形アドレスを保持する) は、スレッド固有のローカル領域を指します。その領域には、そのアドレス (64 ビット) のアドレスがそのアドレスに含まれます。下位アドレスには、すべてのスレッド ローカル変数が格納されます。そのアドレスは native_handle()
です。 .したがって、スレッドのローカルデータにアクセスするには、そのポインターを介してアクセスする必要があります。
つまり:(char*)&variable-(char*)myThread.native_handle()+(char*)theOtherThread.native_handle()
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;
}