Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows


Некоторые соображения по библиотеке С/С++ - часть 6


// блок tiddata сопоставляется с данным потоком

TlsSetValue( __tlsindex ptd);

// идентификатор этого потока записывается в tiddata
((_ptiddata) ptd)->_tid = GetCurrentThreadId();
// здесь инициализируется поддержка операций над числами с плавающей точкой
// (код не показан)

// пользовательская функция потока включается в SEH-фрейм для обработки
// ошибок периода выполнения и поддержки signal
__try
{

// здесь вызывается функция потока, которой передается нужный параметр;
// код завершения потока передается _endthreadex
_endthreadex( ( (unsigned (WINAPI *)(void *))(((_ptiddata)ptd)->_initaddr) ) ( ((_ptiddata)ptd)->_initarg ) ) ;

}

_except(_XcptFilter(GetExceptionCode(), GetExceptionInformation()))
{
// обработчик исключений из библиотеки С не даст нам попасть сюда
_exit(GetExceptionGode());

}

// здесь мы тоже никогда не будем, так как в этой функции поток умирает

return(0L);
}

Несколько важных моментов, связанных со _threadstartex.

  • Новый поток начинает выполнение с BaseThreadStart (в Kernel32.dll), а затем переходит в _threadstartex.
  • В качестве единственного параметра функции _threadstartex передается адрес блока tiddata нового потока,
  • Windows-функция TlsSetValue сопоставляет с вызывающим потоком значение, которое называется локальной памятью потока (Thread Local Storage, TLS) (о ней я расскажу в главе 21), a _threadstartex сопоставляет блок tiddata с новым потоком.
  • Функция потока заключается в SEH-фрейм. Он предназначен для обработки ошибок периода выполнения (например, не перехваченных исключений С++), поддержки библиотечной функции signal и др. Этот момент, кстати, очень ва жен. Если бы Вы создали поток с помощью CreateThread, а потом вызвали биб лиотечную функцию signal, она работала бы некорректно.
  • Далее вызывается функция потока, которой передается нужный параметр. Ад рес этой функции и ее параметр были сохранены в блоке tiddata функцией _beginthreadex.
  • Значение, возвращаемое функцией потока, считается кодом завершения это го потока. Обратите внимание: _threadstartex не возвращается в BaseThreadStart. Иначе после уничтожения потока его блок tiddata так и остался бы в памяти. А это привело бы к утечке памяти в Вашем приложении. Чтобы избежать этого, threadstartex вызывает другую библиотечную функцию, _endthreadex, и пере дает ей код завершения.




Начало  Назад  Вперед