Re: Межпотоковое кидание исключений
От: MaximE Великобритания  
Дата: 03.06.05 22:42
Оценка: 22 (3) +1
On Fri, 03 Jun 2005 16:34:53 +0400, adontz <2053@users.rsdn.ru> wrote:

> Решение судя по всему кросс-компиляторное.

> Что кинуть исключение в другом потоке (и вообще как метод одноразовой передачи сообщения потоку)

[]

> Мне такое удобно делать, чтоб остановить поток слушающий сокет, потому что message-queue там нету и по-другому сообщение не передать.


Куря кольян, на меня снизошло понимание: брошенное таким способом исключение разрушает любой код, включая код с гарантиями strong exception safety и nothrow. Этот метод нельзя использовать никогда, когда предполагается восстановление и продолжение работы после обработки исключения.

Код с гарантиями strong exception safety и nothrow и весь код на С полагается на операции, которые гарантировано не бросают исключений, такие, как, например, многие простые операции над встроенными типами.

Рассмотрим операцию вставки в двусвязанный список. Эта операция является nothrow (конечно при условии, что указатели валидны).

     static node* prepend(node* head, node* n)
     {
         n->prev = head->prev;
         n->next = head;
         head->prev->next = n; // (*)
         return head->prev = n;
     }


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

Если в поток, выполняющий этот код, пробросить исключение предлагаемым варварским методом в тот момент, когда была выполнена строка (*), но не была еще выполнена следующая строка, список будет разрушен. Чтобы этот код сохранил свойство nothrow при таких новых условиях, когда исключение может возникнуть в любой момент из ниоткуда "на ровном месте", возможно необходимо либо каждую строку обернуть в __try / __except конструкцию, либо, возможно, исполнять весь код в блоке __finally (я не спец в SEH). Никто, естественно, в здравом уме этого делать не будет. Примеры подобного кода можно приводить бесконечно.

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

Да, поначалу выглядит круто порулить руками регистрами и наебать остальной код и компилятор, но if you lie to the compiler, it will take its revenge...

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.