Локальная память потока


Все потоки процесса совместно используют свое виртуальное адресное пространство. Локальные переменные функций потока являются уникальными для каждого потока, который запускает функцию. Однако статические и глобальные переменные совместно используются всеми потоками этого процесса. При помощи локальной памяти потока (thread local storage, TLS), Вы можете обеспечивать уникальными данными каждый поток, который может быть допущен процессом к использованию глобального индекса. Используя TLS, один поток назначает индекс, который может быть использован другим потоком, чтобы получить уникальные данные, связанные с этим индексом.

Константа TLS_MINIMUM_AVAILABLE определяет минимальное число индексов локальной памяти потока (TLS), доступных в каждом процессе. Этот минимум гарантируется тем, что для всех системам их будет, по меньшей мере, 64. Ограничения для систем следующие:

 

Система

Лимит

Windows 2000 и позже

1088 индексов на процесс

Windows 98/Me

80 индексов на процесс

Windows 95

Windows NT 4.0 и ранее

64 индексов на процесс

Когда потоки создаются, система выделяет массив значений типа LPVOID для локальной памяти потока (TLS), которые инициализируются значениями ПУСТО (NULL). Раньше индекса, который может быть использован, должен быть назначен один из потоков. Каждый поток сохраняет свои данные по индексу в массиве слотов TLS (TLS slot). Если данные, связанные с индексом соответствуют значению типа LPVOID, Вы можете сохранять данные непосредственно в слоте TLS. Однако если Вы используете большое количество индексов таким образом, лучше выделить отдельную память, объединяющую данные и минимизировать число слотов TLS в использовании.

Нижеследующая диаграмма иллюстрирует, как работает локальная память потока (TLS) .

Процесс имеет два потока, Поток 1 и Поток 2. Назначается два индекса для использования с локальной памятью потока (TLS), gdwTlsIndex1 и gdwTlsIndex2. Каждый поток выделяет два блока памяти (один для каждого индекса) в которых сохраняет данные и сохраняет указатели на эти блоки памяти в соответствующих слотах TLS. Чтобы получить доступ к данным, связанным с индексом, поток извлекает указатель на блок памяти из слота TLS и сохраняет его в локальной переменной lpvData.

Идеально использовать локальную память потока (TLS) в динамически подключаемой библиотеке (DLL). Чтобы реализовать локальную память потока (TLS) в DLL, используйте нижеследующие шаги:

  1. Объявите, что глобальная переменная содержит индекс TLS. Например:

    static DWORD gdwTlsIndex;

  2. Используйте функцию TlsAlloc в ходе инициализации, чтобы назначить индекс локальной памяти потока (TLS). Например, включите следующий вызов функции DllMain во время DLL_PROCESS_ATTACH:
    gdwTlsIndex = TlsAlloc();
  3. Для каждого потока используется индекс локальной памяти потока (TLS), который выделяет память для данных, а затем используется функция TlsSetValue, чтобы сохранить адрес блока памяти в слоте TLS, связанном с индексом. Например, включите нижеследующий код в вашу функцию DllMain во время DLL_THREAD_ATTACH:
    LPVOID lpvBuffer;
    lpvBuffer = (LPVOID) LocalAlloc(LPTR, 256);
    TlsSetValue(gdwTlsIndex, lpvBuffer);
  4. Когда функция требует доступа к данным, связанным с индексом TLS, задайте индекс при вызове функции TlsGetValue. Это извлечет содержание слота TLS для вызывающего потока, который в данном случае является указателем на блок памяти для данных. Например, включите нижеследующий код в любую из функций в вашу DLL:
    LPVOID lpvData;
    lpvData = TlsGetValue(gdwTlsIndex);
  5. Когда каждому потоку больше не нужно использовать индекс TLS, он должен освободить память, указатель на которую сохраняется в слоте TLS. Когда все потоки закончили использовать индексы TLS, используйте функцию TlsFree, чтобы освободить индексы. Например, используйте нижеследующий код в вашей DllMain во время DLL_THREAD_DETACH:
lpvBuffer = TlsGetValue(gdwTlsIndex);
LocalFree((HLOCAL) lpvBuffer);

и нижеследующий код во время DLL_PROCESS_DETACH:

TlsFree(gdwTlsIndex);

 

Пример, иллюстрирующий использование локальной памяти потока, см. в статьях Использование локальной памяти потока и Использование локальной памяти потока в динамически подключаемых библиотеках.

Назад в оглавление темы
На главную страницу темы

Hosted by uCoz