Давайте начнем с кусочком code (Coliru):Thread локальная переменная доступна через не-нить локального объекта
#include <iostream>
#include <thread>
using namespace std;
struct A
{
thread_local static A* p_a;
thread_local static int i;
};
thread_local int A::i;
thread_local A* A::p_a;
int main()
{
A::p_a = new A;
auto lambda = [](A* a)
{
a->i = 1; // Prints 1 (below, of course)
std::cout << a->i << std::endl;
};
std::thread t(std::bind(lambda, A::p_a));
t.join();
// Prints 0 (it hasn't been modified)
std::cout << A::p_a->i << std::endl;
return 0;
}
Как все вы можете видеть, второй поток изменяет свою нить локальную копию A::i
, даже если я доступен это из другого потока локального объекта другого потока. Это ожидаемое поведение? Потому что невозможно получить информацию из другого потока с помощью «referer», если я не передаю указатель или ссылку на объект thread_local, который я хочу прочитать.
С помощью «referer» я ссылаюсь на то, что управляет или может дать вам доступ к своей переменной thread_local из его потока. Но это невозможно! Любое выражение, дающее переменную thread_local, независимо от того, кто (я сделал другой тест, даже с функциями доступа), заканчивается использованием экземпляра thread_local потока чтения.
Я не уверен, что использование потока «thread_local» для обмена данными между потоками соответствует духу хранилища «thread_local». Почему бы просто не использовать обычный «статический»? – Galik
Я просто ... «понимая поведение» (или пытаюсь). –
А ну его синтаксис * * проблема. Просто потому, что вы используете синтаксис, который выглядит так, будто вы разыскиваете указатель 'A', это не так. Компилятор видит, что он является «статическим» и игнорирует указатель и идет прямо для одного (для каждого потока в этом случае) статического экземпляра. Весь бизнес 'thread_local' на самом деле не имеет к этому отношения. – Galik