Как компилятор С++ реализует локальное хранилище потоков в С++ 0x
Я искал это в Google. Но ничего не могу найти по этому поводу.
У кого-нибудь есть материалы по этому поводу??
Как компилятор С++ реализует локальное хранилище потоков в С++ 0x
Я искал это в Google. Но ничего не могу найти по этому поводу.
У кого-нибудь есть материалы по этому поводу??
Прочтите статью Википедии.
Локальное хранилище потока не является чем-то особенным для 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
. Если бы программа была статически компонована, она могла бы быть чем-то вроде указателя на большую структуру со всеми локальными переменными хранения потока, объявленными в программе как элементы. Это упрощение, но общее представление вы поняли.
Очевидно, что доступ к локальным переменным потока не является простым чтением или записью памяти. Это потенциально немного более вовлечено, чем это. Если вы собираетесь часто использовать локальное/специальное хранилище потока в конкретной функции, я бы рекомендовал сначала скопировать указатель локального хранилища потока в локальную переменную.
Глобальные переменные (или доступные для записи статические данные — WSD) обычно хранятся в блоке памяти отдельно от стека, кучи и кода. Блок WSD создается и инициализируется до начала выполнения кода исполняемого файла.
C++0x вводит ключевое слово thread_local
, которое обеспечивает создание отдельного экземпляра глобальной переменной для каждого потока. Проблема в том, что для каждого потока необходимо загружать разные блоки.
Следующая трудность заключается в том, что адрес переменной не фиксируется во время компоновки и различен для каждого потока.
Есть два пути решения этого вопроса. Один из них заключается в том, чтобы компилятор сгенерировал вызов функции для получения правильного блока, а другой — изменить ABI для сохранения блока TLS в одном из регистров процессора. Затем это можно использовать со смещениями для доступа к правильной переменной thread_local
.
Это отличается от поддержки библиотеки, где ОС хранит одно значение void*
, которое можно использовать для хранения указателя на локальный блок потока, выделенный в куче процесса.
Если вам нужны кровавые подробности, посмотрите здесь.
Вы можете использовать boost::thread для переносимо обрабатывать TLS на разных платформах. Реализация каждого из них находится в коде и должна помочь вам понять, как различные системы обрабатывают эту область.