Использование локальной памяти потока (TLS)
Локальная память потока
(TLS) включает многопоточность того же самого процесса, используя индекс, назначенный функцией TlsAlloc, чтобы сохранить и получить значение, которое является локальным к потоку. В этом примере, индекс назначается тогда, когда запускается процесс. Когда запускается каждый поток, он выделяет блок динамической памяти и сохраняет указатель на эту память в слоте TLS, используя функцию TlsSetValue. Функция CommonFunc использует функцию TlsGetValue, чтобы обратиться к данным, связанным с индексом, который является локальным для вызывающего потока. Прежде, чем каждый поток заканчивает работу, он освобождает свою динамическую память. Прежде, чем процесс закончит работу, он вызывает функцию TlsFree, чтобы освободить индекс.
#include <stdio.h> #include <windows.h> #define THREADCOUNT 4 DWORDdwTlsIndex; VOIDErrorExit(LPTSTR); VOIDCommonFunc(VOID) { LPVOID lpvData; // Получим указатель на данные для текущего потока. lpvData = TlsGetValue(dwTlsIndex);if ((lpvData == 0) && (GetLastError() != 0))ErrorExit("TlsGetValue error"); // Используем данные, сохраненные для текущего потока. printf("common: thread %d: lpvData=%lx\n",GetCurrentThreadId(), lpvData);Sleep(5000); } DWORDWINAPI ThreadFunc(VOID) { LPVOID lpvData; // Инициализируем индекс TLS для этого потока. lpvData = (LPVOID) LocalAlloc(LPTR, 256);if (! TlsSetValue(dwTlsIndex, lpvData))ErrorExit("TlsSetValue error");printf("thread %d: lpvData=%lx\n", GetCurrentThreadId(), lpvData);CommonFunc(); // Освободим динамическую память прежде, чем поток возвращает значение. lpvData = TlsGetValue(dwTlsIndex);if (lpvData != 0)LocalFree((HLOCAL) lpvData);return 0; } DWORDmain(VOID) { DWORD IDThread;HANDLE hThread[THREADCOUNT];int i; // Назначим индекс TLS. if ((dwTlsIndex = TlsAlloc()) == -1)ErrorExit("TlsAlloc failed"); // Создадим многопоточность. for (i = 0; i < THREADCOUNT; i++){hThread[i] = CreateThread(NULL, // атрибутов безопасности нет0, // размер стека используем по умолчанию(LPTHREAD_START_ROUTINE) ThreadFunc,// функция потокаNULL, // нет аргументов функции потока0, // флажки создания используются по умолчанию&IDThread); // возвращаем идентификатор потока // Проверим величину возвращаемого значения для успешного завершения. (hThread[i] == NULL)if ErrorExit("CreateThread error\n"); } for (i = 0; i < THREADCOUNT; i++) WaitForSingleObject(hThread[i], INFINITE); TlsFree(dwTlsIndex); return 0; } VOIDErrorExit (LPTSTR lpszMessage) {fprintf(stderr, "%s\n", lpszMessage);ExitProcess(0);} |