Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Критические секции (CRITICAL_SECTION), правильная инициализация и работа 
V
    Опции темы
neokoder
Дата 11.3.2011, 10:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 69
Регистрация: 14.4.2010

Репутация: нет
Всего: -3



Привет коллеги.

Вот у Рихтера прочитал, что иногда InitializeCriticalSection и EnterCriticalSection могут вызывать исключения, очень редко, но всё же могут. Поэтому решил написать 2 универсальные функции инициализации и входа в критическую секцию.

Если у меня есть какие-то "жучки" в коде был бы рад если вы мне на них указали, особенно это касается использования goto, не возникнет ли каких-либо проблем после такого использования. 


Код

#define TRY_INIT_CS_COUNT 10
#define TRY_ENTER_CS_COUNT 10


UINT8 my_InitializeCriticalSectionAndSpinCount(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount)
{
 int i,j;

  j=0; 

again1:
  try
  {
      for (i=0;i<TRY_INIT_CS_COUNT;i++)
      {
         if (InitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount)) return 1;
         SwitchToThread();
      }

  }
  catch(...)
  { 
   j++;
   if (j>=TRY_INIT_CS_COUNT) return 0;
   SwitchToThread();
   goto again1;
  }

  return 0;
}


UINT8 my_TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
  int i,j;

  j=0; 

again2:
  try
  {
      for (i=0;i<TRY_ENTER_CS_COUNT;i++)
      {
         if (TryEnterCriticalSection(lpCriticalSection)) return 1;
         SwitchToThread();
      }

  }
  catch(...)
  { 
   j++;
   if (j>=TRY_ENTER_CS_COUNT) return 0;
   SwitchToThread();
   goto again2;
  }

}


А использовать примерно так:
Код

CRITICAL_SECTION cs1;

//use of my_InitializeCriticalSectionAndSpinCount
if (!my_InitializeCriticalSectionAndSpinCount(&cs1,1000))
{
 printf("Error: can't initialize critical section");
 return 1;
}


//use of my_TryEnterCriticalSection
if (!my_TryEnterCriticalSection(&cs1))
{
  printf("Error: can't enter critical section");
  return 1;
}
else
{
   __try
   {
     //some code
     //...
   }
    __finally
   {
     LeaveCriticalSection(&cs1);
   }
}



Это сообщение отредактировал(а) neokoder - 12.3.2011, 13:52
PM MAIL   Вверх
Estranged
Дата 12.3.2011, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 30.8.2010

Репутация: 3
Всего: 3



Внимательно читайте документацию. Английским по белому написано про эти исключения: MSDN.

This function can raise EXCEPTION_POSSIBLE_DEADLOCK if a wait operation on the critical section times out. The timeout interval is specified by the following registry value: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\CriticalSectionTimeout. Do not handle a possible deadlock exception; instead, debug the application.

Windows 2000:  In low memory situations, EnterCriticalSection can raise an exception. Do not attempt to handle this exception; instead, either terminate the process or allow the exception to pass to the unhandled exception filter. To avoid an exception due to low memory, call the InitializeCriticalSectionAndSpinCount function to preallocate the event used by EnterCriticalSection instead of calling the InitializeCriticalSection function, which forces EnterCriticalSection to allocate the event. Preallocating the event is not necessary on Windows XP or later because EnterCriticalSection is guaranteed not to fail due to lack of resources.

Старина Рихтер хорош, несомненно, но иногда данные там не соответствуют нынешним реалиям.

А второе, теперь разве плюсовые catch ловят SEH исключения от windows? VS 6 точно ловила, а вот 2008 уже нет smile
PM MAIL   Вверх
neokoder
Дата 12.3.2011, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 69
Регистрация: 14.4.2010

Репутация: нет
Всего: -3



Цитата(Estranged @  12.3.2011,  13:32 Найти цитируемый пост)
Внимательно читайте документацию. Английским по белому написано про эти исключения: MSDN.This function can raise EXCEPTION_POSSIBLE_DEADLOCK if a wait operation on the critical section times out. The timeout interval is specified by the following registry value: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\CriticalSectionTimeout. Do not handle a possible deadlock exception; instead, debug the application.Windows 2000:  In low memory situations, EnterCriticalSection can raise an exception. Do not attempt to handle this exception; instead, either terminate the process or allow the exception to pass to the unhandled exception filter. To avoid an exception due to low memory, call the InitializeCriticalSectionAndSpinCount function to preallocate the event used by EnterCriticalSection instead of calling the InitializeCriticalSection function, which forces EnterCriticalSection to allocate the event. Preallocating the event is not necessary on Windows XP or later because EnterCriticalSection is guaranteed not to fail due to lack of resources.


Где вы увидели в моём коде EnterCriticalSection? Внимательно читайте посты. 


Цитата(Estranged @  12.3.2011,  13:32 Найти цитируемый пост)
А второе, теперь разве плюсовые catch ловят SEH исключения от windows? VS 6 точно ловила, а вот 2008 уже нет

Ловят, с ключом компилятора /EHa.

Добавлено через 1 минуту и 6 секунд
Цитата(Estranged @  12.3.2011,  13:32 Найти цитируемый пост)
Старина Рихтер хорош, несомненно, но иногда данные там не соответствуют нынешним реалиям.


Всё там соответствует нынешним реалиям. Читать надо внимательнее.
PM MAIL   Вверх
Estranged
Дата 12.3.2011, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 30.8.2010

Репутация: 3
Всего: 3



Про ключи компилятора я как-то и не подумал.
А что будет, если все 10 попыток TryEnterCriticalSection неудачны? Это типа как ошибка (printf("Error: can't enter critical section");) или все же просто кто-то слишком надолго занял секцию, надо всего лишь чуть-чуть подождать?
PM MAIL   Вверх
neokoder
Дата 13.3.2011, 21:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 69
Регистрация: 14.4.2010

Репутация: нет
Всего: -3



В общем сошлись на другом форуме, что лучше всё же использовать классический вариант.

Проверил работу пары потоков. Если первый поток зависает с завладением критической секции, а второй входит в цикл ожидания освобождения этой крит. секции. Всё -труба! Даже если сделать TerminateThread, а потом DeleteCriticalSection и InitializeCriticalSection всё равно второй поток остаётся висеть. Уже видимо в ожидании непонятно чего.

Хотя я считаю Microsoft могли бы предусмотреть для критических секций такую же штуку как и для мьютекса, т.е. если поток завершается через TerminateThread, то критическая секция должна быть освобождена. Или вообще добавить спец. функцию, позволяющую принудительно освободить критическую секцию.

Тогда остаётся действительно только одно - заключать в критическую секцию только код, который гарантированно не зависнет. А я хотел было написать что-то универсальное, для любого случая... В общем тогда классика - наилучший вариантом будет:
Код
   __try
   {
     EnterCriticalSection(&cs1);
     //some code
   }
    __finally
   {
     LeaveCriticalSection(&cs1);
   }


И InitializeCriticalSectionAndSpinCount вызывать так:
Код
InitializeCriticalSectionAndSpinCount(&cs1,0x80000000|dwSpinCount);

В итоге получим снижение производительности только для Windows 2000, зато упростим себе задачу программирования крит. секций.

Добавлено через 42 секунды
Решено.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0655 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.