Есть ли способ динамически освободить локальное хранилище потоков в Win32 API? - PullRequest
3 голосов
/ 14 июля 2010

Мне нужно использовать локальное хранилище потоков в кроссплатформенном проекте. В * IX я использую pthreads и могу избежать утечек памяти благодаря хорошему указателю функции деструктора, передаваемому в качестве второго аргумента pthread_key_create, но в Windows TlsAlloc такого нет. Также я не могу найти общее место, где любая функция вызывается при выходе из потока (в противном случае я бы доморощил некоторый список указателей функций, которые вызывались при выходе).

В нынешнем виде кажется, что у меня в основном ситуация, когда для фактического использования локального хранилища потока мне нужно выделить собственное пространство в куче и передать указатель на TlsSetValue, но если поток завершается ... У меня нет никакого способа гарантировать, что память была освобождена (кроме кого-то явно вызывающего TlsGetValue и delete / free / HeapFree / etc в конце функции потока.

Кто-нибудь знает лучший способ?

Ответы [ 2 ]

4 голосов
/ 14 июля 2010

Вы можете получить хороший «финализатор», чтобы избавиться от ресурсов, специфичных для потока, даже если поток завершен: используйте RegisterWaitForSingleObject, чтобы дождаться копии (через DuplicateHandle) из дескриптор потоков - вы должны использовать клонированный дескриптор, потому что зарегистрированные ожидания не могут обрабатывать дескриптор {не рассчитан на каламбур} закрытие.
Используйте выделенную кучу структуру / запись для хранения завершенных ресурсов, ожидаемого дескриптора и самого дескриптора ожидания, так как финализатор будет работать в системном пуле потоков, а НЕ в финализированном потоке ( который будет уже мертв к тому времени). И не забудьте доработать финализатор:)

3 голосов
/ 14 июля 2010

Точка входа DLL (DLLmain) вызывается при выходе из потока с кодом причины DLL_THREAD_DETACH.Довольно просто написать DLL, которая отслеживает функции, вызываемые при выходе из потока.

В качестве альтернативы используйте Boost.Thread и функцию boost::this_thread::at_thread_exit для регистрации вызываемой функциипри выходе из потока или используйте boost::thread_specific_ptr, чтобы полностью обернуть использование TLS.

...