Динамическая локальная память потока. Динамическая локальная память потока
Скачать 36 Kb.
|
Динамическая локальная память потока Представим себе такую ситуацию: разрабатывается DLL, одна из функций которой динамически захватывает память для обслуживания приложения. Если эту DLL использует только один поток приложения, то для сохранения указателя на динамически распределенную память достаточно определить в DLL одну переменную. Теперь допустим, что эта DLL используется несколькими потоками одного приложения. В этом случае возникают следующие проблемы. Во-первых, нужно где-то хранить указатели на захваченную память, ведь заранее неизвестно, сколько потоков будут параллельно использовать DLL. Во-вторых, функция из DLL должна как-то узнать — какой поток ее вызывает, чтобы сопоставить каждому потоку свой указатель. Для решения подобных задач и предназначена динамическая локальная память потока. Динамическая локальная память потока (thread local storage, TLS) представляет собой массив указателей, доступ к которым осуществляется через индексы при помощи специальных функций Win32 API. Этот массив указателей автоматически поддерживается операционной системой для каждого потока и содержит, по меньшей мере, tls_minimum_available указателей. Порядок работы с локальной памятью потока следующий: □ распределение указателя; □ работа с указателем; □ освобождение указателя. Прежде чем использовать какой-либо указатель, его нужно распределить. Это делается при помощи функции TisAiioc. После распределения указателя для каждого потока становится доступной своя копия этого указателя. Для работы с указателями локальной памяти потока используются функции TisSetvalue и TisGetvalue, которые соответственно записывают некоторое значение и читают значение из локальной памяти потока. После окончания работы с указателем его нужно освободить, вызвав функцию TisFree. В следующих далее разделах будет описана подробно работа со всеми этими функциями. Распределение и освобождение локальной памяти потока Прежде чем использовать какой-либо указатель из локальной памяти потока, его нужно распределить. Для этой цели используется функция TisAiioc, которая имеет следующий прототип: DWORD TlsAlloc(VOID); Эта функция не имеет параметров и в случае успешного завершения возвращает индекс распределенного указателя из локальной памяти потока. При этом распределенный указатель инициализирован в ноль. Если функция закончилась неудачей, то она возвращает -1. Неудача при выполнении этой функции, скорее всего, означает, что локальная память потока исчерпана. Для освобождения распределенного указателя из локальной памяти потока используется функция TisFree, которая имеет следующий прототип: BOOL TisFree( DWORD dwTlsIndex // TLS-индекс ); В случае успешного завершения эта функция возвращает ненулевое значение, а в случае неудачи — false. Единственным параметром этой функции является индекс освобождаемого указателя из локальной памяти потока. Примеры вызова этих функций приведены в следующем разделе, который содержит программы, иллюстрирующие работу с динамической локальной памятью потока. Запись и чтение из локальной памяти потока Для записи значения в локальную память потока используется функция TisSetvalue, которая имеет следующий прототип: BOOL TisSetvalue( DWORD dwTlsIndex, // TLS-индекс LPVOID lpTlsValue // запоминаемое значение ); В случае успешного завершения эта функция возвращает ненулевое значение, а в случае неудачи — false. Параметр dwTis index этой функции должен содержать индекс элемента в массиве указателей, а само значение, запоминаемое в этом элементе массива, передается через параметр lpTlsValue. Для чтения значения из динамической локальной памяти потока используется функция TisGetvalue, которая имеет следующий прототип: LPVOID TlsGetValue( DWORD dwTisIndex // TLS-индекс ); В случае успешного завершения эта функция возвращает значение, хранимое в локальной памяти потока с индексом dwTisindex, а в случае неудачи — ноль. В листинге приведена программа, которая иллюстрирует работу с рассмотренными функциями. Эта программа распределяет все указатели из локальной памяти потока, а затем освобождает их. При этом для запоминания индексов распределенных указателей используются сами указатели. |