вторник, 28 декабря 2010 г.

TLS. Локальное хранилище потока.

Идея проста.Если нужна использовать глобальные переменные для потока,то как решить проблему использование одной и той же памяти разными потоками.Есть решение - TLS.
В небольшом примере всё будет видно.

#include "stdafx.h"
#include "iostream"
#include "string.h"
#include "windows.h"
using namespace std;

// Глобальные переменные
int tls_int;
char simple_char[25];
DWORD tls_char;
/*!
* Потоковая функция
* \param param - параметр потоковой функции
* \return - результат работы потоковой функции
*/
DWORD WINAPI ThreadFunc(LPVOID param);
/*!
* Потоковая функция использующая технологию TLS
* \param param - параметр потоковой функции
* \return - результат работы потоковой функции
*/
DWORD WINAPI ThreadFuncTls(LPVOID param);
/*!
* Главная функция программы
*/
int _tmain(int argc, _TCHAR* argv[])
{
char variant[20];
DWORD threadId;
cout << "Enter method - ";
cin >> variant;
if (!strcmp(variant,"simple"))
{
CreateThread(NULL,0,ThreadFunc,(LPVOID)1,0,&threadId);
CreateThread(NULL,0,ThreadFunc,(LPVOID)2,0,&threadId);
Sleep(10000);
}
if (!strcmp(variant,"tls"))
{
/*
Прототип
DWORD WINAPI TlsAlloc(void);
TlsAlloc - резервирует свободный блок памяти
который будет принаджежать только потоку внутри
которого она вызывалась.
Возвращает индекс ячейки зарезервированной памяти,
если память невозможно выделить возвращает TLS_OUT_OF_INDEXES .
*/
tls_int = TlsAlloc();
tls_char = TlsAlloc();
CreateThread(NULL,0,ThreadFuncTls,(LPVOID)1,0,&threadId);
CreateThread(NULL,0,ThreadFuncTls,(LPVOID)2,0,&threadId);
Sleep(10000);
TlsFree(tls_int);
TlsFree(tls_char);
}
return 0;
}
DWORD WINAPI ThreadFunc(LPVOID param)
{
// юзаем глобальные переменные
tls_int = (int)param;
strcpy(simple_char,"array symbol");
Sleep(tls_int);
cout << "Parameter = " << tls_int << endl;
cout << "string : " << simple_char << endl;
return 0 ;
}
DWORD WINAPI ThreadFuncTls(LPVOID param)
{
/*
Прототип
BOOL WINAPI TlsSetValue(
__in DWORD dwTlsIndex,
__in LPVOID lpTlsValue
);
TlsSetValue - Можно догадаться функция заносит
в выделеную локальную память потока значение.
Первым параметром является индекс выделенной ячейки памяти,
т.е то что нам вернула функция TlsAlloc.
Вторым же значение которое надо занясти в память.
*/
TlsSetValue(tls_int,param);
char buffer[25];
strcpy(buffer,"array symbol");
TlsSetValue(tls_char,buffer);
/*
Прототип
LPVOID WINAPI TlsGetValue(__in DWORD dwTlsIndex);
TlsGetValue - Функция возвращает значение из заразервированной
ячейки памяти.
Параметром является индекс зарезервированной ячейки памяти.
*/
Sleep((DWORD)TlsGetValue(tls_int));
cout << "Parametr = " << (DWORD)TlsGetValue(tls_int) << endl;
cout << "string : " << (char *)TlsGetValue(tls_char)<< endl;
return 0;
}