Почему член OwningThread элемента CRITICAL_SECTION типа HANDLE, когда он обозначает идентификатор потока?

Я пытаюсь добавить проверку отладки для кода разблокировки CRITICAL_SECTION, и я попробовал следующее:

...
if (m_pCritSect) {
ASSERT(m_pCritSect->OwningThread == GetCurrentThreadId());
LeaveCriticalSection(m_pCritSect);
}
}

От отладки CRITICAL_SECTIONS (с VS 2005, в основном на WindowsXP) я «знаю», что значение OwningThread (член RTL_CRITICAL_SECTION структура определена в winnt.h) значение th Я БЫ нити, удерживающей замок.

Однако идентификаторы потоков представлены DWORD (typedef для unsigned long) значения, пока эта переменная имеет тип HANDLE (typedef для void*) требующий reinterpret_cast за использование HandleToULong Макрос из basetsd.h чтобы вышеприведенный код работал.

Даже Документы MSDN государство:

Когда первый поток вызывает подпрограмму EnterCriticalSection, (…)
OwningThread становится идентификатором потока вызывающей стороны.

Так почему же это определяется как HANDLE?


Редактировать Примечание: я нашел заявление где плакат указывает на то, что несоответствие HANDLE / DWORD-Id является известным недостатком некоторых внутренних компонентов Windows. Так что, может быть, это также и здесь:

GetCurrentThreadId возвращает DWORD, который я отправляю ядру в
сообщение. PsLookupThreadByThreadId принимает идентификатор потока в HANDLE, …

Это известная ошибка Windows API («известная» в том, что я говорил с
Соответствующий диспетчер фильтров DEV об этом, как это показано в фильтре
Диспетчер также из-за проблемы API диспетчера ввода-вывода.) Пока вы
не имеют более полумиллиарда или около того потоков и процессов (они
используйте одну общую таблицу дескрипторов) все будет в порядке. Может к тому времени
это реальная проблема, мы будем работать что-то другое. [RE: ThreadId для HANDLE для 64 бит?, 08 августа 08 14:21, Тони Мейсон]

7

Решение

Любой идентификатор в SDK, имя которого начинается с RTL или Rtl, является кодом или объявлениями, которые являются частью уровня времени выполнения, связующим звеном между хорошо документированным Winapi и недокументированным собственным API операционной системы. Winapi сделан из камня, родная операционная система сильно меняется с каждым выпуском Windows. Неизбежно, клей также меняется.

Winapi — это документированный слой, а собственная операционная система не имеет документов. Слой среды выполнения также был недокументирован, но со временем его части были обнаружены. Либо потому, что он заполняет недостающую особенность в Winapi. Или, в этом случае, потому что это действительно полезно для устранения проблем. Однако одна из основных проблем заключается в том, что после объявления декларации Microsoft больше не сможет ее изменить. Потому что это нарушит существующие программы, что станет большим бременем для их клиентов.

Так что, конечно, поле ThreadOwner когда-то действительно содержало дескриптор потока в предыдущей версии Windows. Обратите внимание, что LockSemaphore также вводит в заблуждение, на самом деле это событие автоматического сброса. Слишком поздно, чтобы это исправить, кошка вышла из сумки.

8

Другие решения

Я считаю, что главная причина в том, что это деталь реализации. Я не удивлюсь, если когда-то в истории это будет действительно ручка или что-то в этом роде.

Кроме того, я настоятельно рекомендую не использовать внутренние элементы в производственном коде, и я не один. Если вы посмотрите внимательно, API-интерфейсы синхронизации используют CRITICAL_SECTION который вы не найдете документированным как структура в MSDN, а не RTL_CRITICAL_SECTION (который определен как CRITICAL_SECTION)

Значение, которое хранится в OwningThread член взят из CLIENT_ID часть Блок информации о потоках. В CLIENT_ID он моделируется как PVOID, поэтому, вероятно, он моделируется таким же образом в CRITICAL_SECTION:

typedef struct _CLIENT_ID
{
PVOID UniqueProcess;
PVOID UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
4

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector