Как компилятор C ++ реализует локальное хранилище потоков в C ++ 0x? - PullRequest
12 голосов
/ 17 сентября 2010

Как c ++ complier реализует локальное хранилище потоков в C ++ 0x

Я искал это в Google. Но я ничего не могу найти по этому поводу.

У кого-нибудь есть материал по этому поводу?

Ответы [ 3 ]

14 голосов
/ 17 сентября 2010

Прочитайте запись Википедии .

Локальное хранилище потоков не является чем-то особенным для C ++. Иногда это происходит под разными именами, например, «TLS» (просто сокращение локального хранилища потока) или «хранилище, специфичное для потока» (TSS).

Большинство операционных систем предоставляют API для доступа к хранилищу для каждого потока. Например, в Windows есть набор API-функций , начинающихся с "TLS". Под капотом Win32 резервирует специальную область для различных данных для каждого потока, включая локальное хранилище пользовательских потоков, доступное через определенный регистр ЦП (FS на x86). Linux обеспечивает специфичное для потока хранилище через API-интерфейсы pthread с именами, такими как pthread_key_create , и они, как правило, реализуются с использованием аналогичной техники.

Возможно, ОС вообще не оказывает никакой поддержки. Однако, если ОС предоставляет уникальный идентификатор потока процесса через API, тогда библиотека времени выполнения C ++ могла бы поддерживать что-то концептуально, например, std::map<thread_id, per_thread_storage> внутри. Конечно, тогда возникает проблема, что такое per_thread_storage. Если программа статически связана, это может быть что-то вроде указателя на большую структуру со всеми переменными локального хранилища, объявленными в программе как элементы. Это упрощение, но вы получите общее представление.

Доступ к локальным переменным хранилища, очевидно, не просто чтение или запись в памяти. Это потенциально немного более сложно, чем это. Если вы собираетесь использовать локальное / конкретное хранилище потока в определенной функции, я бы рекомендовал сначала скопировать указатель локального хранилища потока в локальную переменную.

5 голосов
/ 17 сентября 2010

Глобальные переменные (или записываемые статические данные - WSD) обычно хранятся в блоке памяти отдельно от стека, кучи и кода. Блок WSD создается и инициализируется до запуска исполняемого кода.

C ++ 0x вводит ключевое слово thread_local, которое обеспечивает создание отдельного экземпляра глобальной переменной для потока. Проблема в том, что для каждого потока необходимо загрузить другой блок.

Следующая трудность заключается в том, что адрес переменной не фиксирован во время соединения и отличается для каждого потока.

Есть два пути решения этой проблемы. Один из них заключается в том, что компилятор должен генерировать вызов функции для получения правильного блока, а другой - изменять ABI для сохранения блока TLS в одном из регистров процессора. Затем его можно использовать со смещениями для доступа к правильной переменной thread_local.

Это отличается от поддержки библиотеки, когда ОС хранит одно значение void*, которое можно использовать для хранения указателя на локальный блок потока, выделенный в куче процесса.

Если вы хотите узнать подробности, смотрите здесь .

0 голосов
/ 17 сентября 2010

Вы можете использовать boost :: thread для переносимой обработки TLS на разных платформах.Реализация каждого из них приведена в коде и должна помочь вам понять, как разные системы обрабатывают эту область.

...