Шаг 126 - Динамическая локальная память потоков TlsAlloc - TlsFree

Здесь все сложнее. Эта память будет создана во время работы приложения, как и обычная динамическая память. Идея та же. Используя этот тип памяти у нас отпадает необходимость заботиться о синхронизации памяти между потоками. Первое это надо запросить у системы индекс динамической локальной памяти потоков это делает TlsAlloc.

DWORD TlsAlloc(VOID);

Если функция успешна она вернет индекс памяти, иначе вернет -1;

DWORD dwTlsIndex;
dwTlsIndex=TlsAlloc();
if (dwTlsIndex==-1) 
{
	cout << "Error TlsAlloc " << endl;
	return;
}

В конце завершения работы потока индекс надо освободить. Это реализует функция -

BOOL TlsFree(
	DWORD dwTlsIndex	//TLS index
);

При успехе возвращаемое значение ненулевое.

if ( TlsFree( dwTlsIndex)==0 ) 
{
	cout << "Error TlsFree" << endl;
	return;
}

К чему все это? Я понимаю, что на примере просто одной программы это не совсем понятно. А вот представьте себе, что Вы организуете DLL. К которой будут обращаться много программ. Ведь код DLL в памяти храниться в одном экземпляре. Соответственно надо гарантировать что каждый процесс, который обратиться к DLL будет иметь свою локальную динамическую память. Что бы один процесс не испортил данные другого процесса. Вот к чему все это. Хоть статическая локальная память процесса, хоть динамическая локальная память процесса нужна если к одной и той же функции будут обращаться много потоков. Обе эти памяти только по своему гарантируют локальность данных. К примеру, о DLL. В момент подключения процесса он должен создать свою динамическую локальную память, а в момент отключения освободить. То есть не процесс должен это делать в DLL должна уметь это делать. Вот примерно так. Это совсем простой пример так как в процессе может быть много потоков.

BOOL APIENTRY DllMain(HANDLE hInst, ULONG uCall, LPVOID
	lpReserved)
{
	......
	switch(uCall) 
	{
		case DLL_PROCESS_ATTACH:
		{
			dwTlsIndex = TlsAlloc();
			......
		}

		case DLL_PROCESS_DETACH:
		{
			TlsFree(dwTlsIndex);
			......
		}
		......
	}
	......
}

Ну и полный пример:

#include "stdafx.h"
#include "windows.h"
#include "iostream.h"
#include "process.h"			// специально для потока

void  fThredFunct1(void* pv);		// декларация функции потока
__declspec(thread) DWORD dwTlsIndex;		// локальная статическая функция для потока

void main()
{

	ULONG hThread1 = 0;		// Идентификатор потока 1
	ULONG hThread2 = 0;		// Идентификатор потока 2
	//unsigned long _beginthread( void( __cdecl *start_address )( void * ),
	//			unsigned stack_size, void *arglist );
	hThread1 = _beginthread(fThredFunct1,0,NULL);	// создали первый поток
	if (hThread1==-1)
		cout << "Error create thread" << endl; 
	hThread2 = _beginthread(fThredFunct1,0,NULL);	// создали второй поток
	if (hThread1==-2)
		cout << "Error create thread" << endl; 
	Sleep(2000);				// ждем 
}

void fThredFunct1(void* pv)			// реализация функции потока
{
	dwTlsIndex=TlsAlloc();		// Запросить индекс
	if (dwTlsIndex==-1)		// проверить на ошибку
	{
		cout << "Error TlsAlloc " << endl;
		return;
	}
	cout << dwTlsIndex << endl;
	Sleep(1000);

	if ( TlsFree( dwTlsIndex)==0 )	// освободить индекс
	{
		cout << "Error TlsFree" << endl;
		return;
	}
}

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


Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем - 06.07.2001