Как отловить исключение в критическом разделе? - PullRequest
4 голосов
/ 19 марта 2009

Я работаю над многопоточностью win 32 с c ++. Сценарий: У меня есть функция, используемая несколькими потоками. Эта функция является критической секцией (или любой конструкцией, которая может заблокировать ресурс). В критическом разделе выдается исключение. На данный момент мне нужно позаботиться о разблокировке ресурса в блоке перехвата исключений.

Есть ли другой способ сделать это? Я имею в виду, скажем, я не хочу вспоминать, чтобы снять блокировку в блоке catch, есть ли какой-нибудь общий способ решения этой проблемы, чтобы избежать сценария, склонного к ошибкам?

Ответы [ 4 ]

16 голосов
/ 19 марта 2009

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

struct CSHolder {
    explicit CSHolder(CRITICAL_SECTION& cs): lock(cs) {
        ::EnterCriticalSection(&lock);
    }
    ~CSHolder() { ::LeaveCriticalSection(&lock); }
    CRITICAL_SECTION& lock;
};


CRITICAL_SECTION gLock;
void foo() {
    CSHolder lockIt(gLock);
    // lock is held until lockIt is destroyed
}

Концепция называется RAII - Приобретение ресурсов - Инициализация. Это очень распространенная идиома в современном C ++.

3 голосов
/ 19 марта 2009

Если вы используете существующую платформу, у вас, вероятно, уже есть класс контейнера RAII, который может сделать это за вас. Если вы используете MFC, посмотрите на CSingleLock, если вы используете усиленный взгляд на scoped_lock.

Это позор, что каждый, кажется, должен (или думает, что должен) бросить свой собственный.

2 голосов
/ 19 марта 2009

Если вы можете использовать MFC, вы можете использовать CSingleLock для этого. Вы можете использовать это так:

void f()
{
  try
  {
    CSingleLock lock(&m_criticalSection, TRUE);

  }
  catch(/*some exception*/)
}

Замок позаботится о разблокировке критической секции в своем деструкторе. Поскольку блокировка является локальным объектом, когда выбрасывается исключение, стек раскручивается, а деструктор объектов блокировки выполняется, разблокируя критический раздел.

2 голосов
/ 19 марта 2009

Напишите класс скобок, который принимает критический раздел в качестве параметра конструктора. Вызовите EnterCriticalSection в конструкторе и LeaveCriticalSection в деструкторе. Разматывание стека сделает все остальное, если возникнет исключение C ++.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...