Могу ли я получить идентификатор потока, который содержит CriticalSection? - PullRequest
2 голосов
/ 27 ноября 2010

Я хочу написать несколько утверждений вокруг сложного многопоточного кода.Есть ли способ сделать

assert(GetCurrentThreadId() == ThreadOfCriticalSection(sec));

Ответы [ 3 ]

4 голосов
/ 27 ноября 2010

Если вы хотите сделать это правильно, я думаю, что вы использовали объект-оболочку вокруг ваших критических секций, который будет отслеживать, какой поток (если таковой имеется) владеет каждым CS в отладочных сборках.

т.е. вместо прямого вызова EnterCriticalSectionВы бы вызвали метод в вашей обертке, который выполнил EnterCriticalSection, а затем, при успешном выполнении, сохранил GetCurrentThreadId в DWORD, который проверят утверждения.Другой метод обнуляет этот идентификатор потока DWORD перед вызовом LeaveCriticalSection.

(В сборках релиза оболочка, вероятно, пропустит лишние вещи и просто вызовет Enter / LeaveCriticalSection.)

Как указывает Касабланка,идентификатор потока владельца находится в текущей структуре CRITICAL_SECTION, поэтому использование оболочки, как я предлагаю, будет хранить избыточную информацию.Но, как указывает Касабланка, структура CRITICAL_SECTION не является частью какого-либо контракта API и может измениться.(Фактически, изменилось в предыдущих версиях Windows.)

Знание внутренней структуры полезно для отладки, но не должно использоваться в производственном коде.

Так чтоМетод, который вы используете, зависит от того, насколько «правильным» будет ваше решение.Если вам просто нужны временные подтверждения для отслеживания проблем сегодня, в текущей версии Windows, то использование полей CRITICAL_SECTION напрямую мне кажется разумным.Только не ожидайте, что эти утверждения будут действительны вечно.Если вы хотите что-то, что будет работать дольше, используйте оболочку.

(Другое преимущество использования оболочки - получение RAII. Т.е. конструктор и деструктор оболочки будут заботиться о вызовах InitializeCriticalSection и DeleteCriticalSection, поэтомувам больше не нужно беспокоиться о них. Говоря об этом, я считаю чрезвычайно полезным иметь вспомогательный объект, который входит в CS при построении, а затем автоматически оставляет его при разрушении. Больше нет критических секций, случайно оставленных заблокированными, потому что функция имела раннийвернуть спрятанный в середине этого ...)

1 голос
/ 27 ноября 2010

Насколько я знаю, не существует документированного способа получения этой информации. Если вы посмотрите на заголовки, структура CRITICAL_SECTION содержит дескриптор потока, но я бы не стал полагаться на такую ​​информацию, потому что внутренние структуры могут изменяться без уведомления. Лучшим способом было бы сохранить эту информацию самостоятельно всякий раз, когда поток входит / выходит из критической секции.

0 голосов
/ 27 ноября 2010

Ваше требование не имеет смысла.Если ваш текущий поток не является потоком, находящимся в критическом разделе, то код в текущем потоке не будет работать, он будет заблокирован при попытке заблокировать критический раздел.

Если ваш потокна самом деле внутри критического раздела, то ваше утверждение всегда будет верным.Если это не так, ваше утверждение всегда будет ложным!

Итак, я имею в виду, что если вы в состоянии отследить, какой поток находится в критическом разделе, если вы поместите свое утверждение в код критического раздела,всегда буду правдойЕсли вы разместите его снаружи, оно всегда будет ложным.

...