Динамическая локальная память потока
Представим себе такую ситуацию: разрабатывается 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, а в случае неудачи —
ноль.
В листинге приведена программа, которая иллюстрирует работу с
рассмотренными функциями. Эта программа распределяет все указатели из
локальной памяти потока, а затем освобождает их. При этом для запоминания
индексов распределенных указателей используются сами указатели.
Достарыңызбен бөлісу: |