Я пытаюсь добавить проверку отладки для кода разблокировки 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, Тони Мейсон]
Любой идентификатор в SDK, имя которого начинается с RTL или Rtl, является кодом или объявлениями, которые являются частью уровня времени выполнения, связующим звеном между хорошо документированным Winapi и недокументированным собственным API операционной системы. Winapi сделан из камня, родная операционная система сильно меняется с каждым выпуском Windows. Неизбежно, клей также меняется.
Winapi — это документированный слой, а собственная операционная система не имеет документов. Слой среды выполнения также был недокументирован, но со временем его части были обнаружены. Либо потому, что он заполняет недостающую особенность в Winapi. Или, в этом случае, потому что это действительно полезно для устранения проблем. Однако одна из основных проблем заключается в том, что после объявления декларации Microsoft больше не сможет ее изменить. Потому что это нарушит существующие программы, что станет большим бременем для их клиентов.
Так что, конечно, поле ThreadOwner когда-то действительно содержало дескриптор потока в предыдущей версии Windows. Обратите внимание, что LockSemaphore также вводит в заблуждение, на самом деле это событие автоматического сброса. Слишком поздно, чтобы это исправить, кошка вышла из сумки.
Я считаю, что главная причина в том, что это деталь реализации. Я не удивлюсь, если когда-то в истории это будет действительно ручка или что-то в этом роде.
Кроме того, я настоятельно рекомендую не использовать внутренние элементы в производственном коде, и я не один. Если вы посмотрите внимательно, 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;