Теперь потенциально последний вызов
IObject2::Release() будет осуществлен после выхода из критической секции. А
присвоение нового значения по-прежнему синхронизовано с вызовом
IObject2::SomeMethod() из нити №1.
Способы обнаружения ошибок
Сначала стоит обратить внимание на
"официальный" способ обнаружения блокировок. Если бы кроме
::EnterCriticalSection() и ::TryEnterCtiticalSection() существовал еще и
::EnterCriticalSectionWithTimeout(), то достаточно было бы просто указать
какое-нибудь резонное значение для интервала ожидания, например, 30 секунд.
Если критическая секция не освободилась в течение указанного времени, то с
очень большой вероятностью она не освободится никогда. Имеет смысл подключить
отладчик и посмотреть, что же творится в соседних нитях. Но увы. Никаких
::EnterCriticalSectionWithTimeout() в Win32 не предусмотрено. Вместо этого есть
поле CriticalSectionDefaultTimeout в структуре IMAGE_LOAD_CONFIG_DIRECTORY32, которое всегда равно нулю и, судя по всему, не используется. Зато используется
ключ в реестре "HKLMSYSTEMCurrentControlSetControlSession
ManagerCriticalSectionTimeout", который по умолчанию равен 30 суткам, и
по истечению этого времени в системный лог попадает строка "RTL: Enter
Critical Section Timeout (2 minutes)nRTL: Pid.Tid XXXX.YYYY, owner tid
ZZZZnRTL: Re-Waitingn". К тому же это верно только для систем
WindowsNT/2k/XP и только с CheckedBuild. У вас установлен CheckedBuild? Нет? А
зря. Вы теряете исключительную возможность увидеть эту замечательную строку.
Ну, а какие у нас альтернативы? Да, пожалуй, только
одна. Не использовать API для работы с критическими секциями. Вместо них
написать свои собственные. Пусть даже не такие обточенные напильником, как в
Windows NT. Не страшно. Нам это понадобится только в debug-конфигурациях. В
release'ах мы будем продолжать использовать оригинальный API от Майкрософт. Для
этого напишем несколько функций, полностью совместимых по типам и количеству
аргументов с "настоящим" API, и добавим #define, как у MFC, для
переопределения оператора new в debug-конфигурациях.
Листинг 14. Собственная реализация критических секций.
#if defined(_DEBUG) && !defined(_NO_DEADLOCK_TRACE)
#define DEADLOCK_TIMEOUT 30000
#define CS_DEBUG 1
// Создаем на лету событие
для операций ожидания,
// но никогда его не
освобождаем. Так
удобней для отладки
static inline HANDLE _CriticalSectionGetEvent(LPCRITICAL_SECTION pcs)
{
HANDLE ret =
pcs->LockSemaphore;
if (!ret)
{
HANDLE sem =
::CreateEvent(NULL, false, false, NULL);
ATLASSERT(sem);
if (!(ret =
(HANDLE)::InterlockedCompareExchangePointer(
&pcs->LockSemaphore, sem, NULL)))
ret = sem;
else Рекомендуем скачать другие рефераты по теме: реферат на экономическую тему, инновационная деятельность.
Предыдущая страница реферата | 10
11
12
13
14
15
16
17
18
19
20 | Следующая страница реферата
|
|