Bohužel jsem nikdy nenašel způsob, jak to udělat.
Bez nějakého druhu init háčku vlákna se prostě nezdá být způsob, jak se dostat k tomuto ukazateli (krátké ASM hacky, které by byly závislé na platformě).
Pokud chcete lokální proměnné vlákna, které nejsou lokální, proč místo toho nepoužijete globální proměnné?
Důležité vysvětlení!
Nenavrhuji, abyste k nahrazení lokální proměnné vlákna používali jedinou globální. Navrhuji použít jediné globální pole nebo jinou vhodnou sbírku hodnot k nahrazení jedné lokální proměnné vlákna.
Samozřejmě budete muset zajistit synchronizaci, ale protože chcete vystavit hodnotu upravenou ve vláknu A vláknu B, nelze to obejít.
Aktualizace:
Dokumentace GCC na __thread
říká:
Když je operátor address-of aplikován na lokální proměnnou podprocesu, vyhodnotí se za běhu a vrátí adresu aktuální instance této proměnné. Takto získanou adresu může použít jakékoli vlákno. Když vlákno skončí, všechny ukazatele na místní proměnné vlákna v tomto vláknu se stanou neplatnými.
Pokud tedy trváte na tom, že půjdete tímto způsobem, představuji si, že je možné získat adresu lokální proměnné vlákna z vlákna, ke kterému patří, hned po vytvoření vlákna. Pak byste mohli uložit ukazatel na toto paměťové místo do mapy (id vlákna => ukazatel) a umožnit ostatním vláknům přistupovat k proměnné tímto způsobem. To předpokládá, že vlastníte kód vytvořeného vlákna.
Pokud jste opravdu dobrodružní, můžete zkusit najít informace na ___tls_get_addr
(začněte z tohoto PDF, na který odkazují výše uvedené dokumenty GCC). Ale tento přístup je tak silně specifický pro kompilátor a platformu a tak postrádá dokumentaci, že by měl způsobovat poplachy v hlavě každého.
Hledám to samé. Jak vidím, nikdo na vaši otázku neodpověděl poté, co jsem všemi způsoby prohledal web, dospěl jsem k následným informacím:předpokládá se kompilace pro gcc na linuxu (ubuntu) a pomocí -m64, segmentový registr gs má hodnotu 0. Skrytá část segmentu (držící lineární adresu) ukazuje na místní oblast specifickou pro vlákno. Tato oblast obsahuje na této adrese adresu této adresy ( 64 bitů ). Na nižších adresách jsou uloženy všechny lokální proměnné vlákna. Tato adresa je native_handle()
.Takže abyste získali přístup k místním datům vláken, měli byste to udělat přes tento ukazatel.
Jinými slovy:(char*)&variable-(char*)myThread.native_handle()+(char*)theOtherThread.native_handle()
Kód, který demonstruje výše uvedené, za předpokladu g++,linux,pthreads je:
#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;
}