Как обращаться с общими данными при создании исключений

При наличии нескольких потоков, использующих общие данные, как правильно обрабатывать уничтожение этих данных при возникновении исключений?

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

class Notifier {
public:
Notifier(Client* _client) : value(-1), client(_client) {
listener = boost::thread(&Notifer::Listen, this);
}

void Listen() {
try {
int rec = client->Receive(); //blocking call to receive data over a socket
boost::scoped_lock sl(mutex);
value = rec;
} catch (...) {
cout << "Exception thrown in listener" << endl;
}
}

int Get() {
boost::mutex::scoped_lock sl(mutex);
return value;
}

private:
int value;
boost::mutex;
boost::thread listener;
Client* client;
}

int main() {
Client client; //initialize client, connect, etc.
Notifier n(client);
while(n.Get() < 0) {
// do work
cout << "Waiting for data" << endl;
sleep(1);
}
}

Это прекрасно работает для меня, пока я не добавлю обработку исключений:

int main() {
try {
Client client; //initialize client, connect, etc.
Notifier n(client);
while(n.Get() < 0) {
// do work
cout << "Waiting for data" << endl;
sleep(1);
throw exception();
}
} catch(...) {
cout << "Exception thrown in main" << endl;
}
return 0;
}

Я получаю ошибку

msgstr «boost: блокировка мьютекса не удалась в pthread_mutex_lock: неверный аргумент».

Я предполагаю, что когда генерируется исключение, стек для main Функция раскручивается, уничтожая мьютекс. Тогда Receive() позвонить в Listen функция возвращает и scoped_lock Конструктор пытается заблокировать мьютекс, который не существует, что приводит к ошибке.

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

0

Решение

Вы должны написать правильный деструктор для Notifier класс, который будет отменять все заблокированные вызовы (т.е. разблокировать client->Receive()), а затем прекратить listener нить. Также вам нужно изменить Notifier::Listen() периодически проверять запрос завершения потока … тогда все будет хорошо.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]