Поместите критические функции в деструктор, чтобы «улучшить атомарность»?

Скажем, у меня есть две функции C ++ foo1 () и foo2 (), и я хочу минимизировать вероятность того, что foo1 () начнет выполнение, но foo2 () не вызывается из-за какого-то внешнего события. Я не против, если ни один из них не вызывается, но foo2 () должна выполняться, если была вызвана foo1 (). Обе функции могут быть вызваны последовательно и не выдают исключений.

Есть ли какая-то польза / недостаток в обертывании функций в объекте и вызове обоих в деструкторе? Изменится ли ситуация, если приложение будет многопоточным (скажем, сбой родительского потока)? Существуют ли другие варианты обеспечения вызова функции foo2 (), если вызывается функция foo1 ()?

Я думал, что наличие их в деструкторе может помочь, например, SIGINT, хотя я узнал, что SIGINT немедленно остановит выполнение, даже в середине деструктора.

Редактировать:

Для пояснения: и foo1 (), и foo2 () будут абстрагированы, поэтому я не беспокоюсь о том, что кто-то вызовет их в неправильном порядке. Мое беспокойство связано исключительно со сбоями, исключениями или другими прерываниями во время выполнения приложения (например, кто-то нажимает SIGINT, происходит сбой другого потока и т. Д.).

0

Решение

Если происходит сбой другого потока (без соответствующего обработчика сигнала -> завершается все приложение), вы мало что можете сделать, чтобы гарантировать, что ваше приложение что-то делает — это зависит от того, что делает ОС. И ВСЕГДА есть случаи, когда система убивает ваше приложение без вашего ведома (например, ошибка, которая приводит к тому, что «все» память используется вашим приложением, а ОС «убивает память», убивая ваш процесс).

Единственный раз, когда ваш деструктор гарантированно будет выполнен, это если объект создан и выдается исключение C ++. Все сигналы и тому подобное, не дают таких гарантий и продолжают работать [в том же потоке] после того, как, например, SIGSEGV или SIGBUS находятся в «неопределенных» частях мира — ничего с этим не поделаешь, так как SEGV обычно означает «вы пытались сделать что-то с памятью, которой не существует [или к которой у вас нет доступа, как вы пытались, например, записать в память кода]», и процессор прервал бы текущую инструкцию. Попытка продолжить, где бы вы ни находились, приведет либо к повторному выполнению той же самой инструкции, либо к пропущенной инструкции [если вы продолжите на следующей инструкции — и я игнорирую проблему определения, где это сейчас находится]. И, конечно, бывают ситуации, когда НЕВОЗМОЖНО продолжать работу, даже если вы хотите — например, указатель стека был поврежден [восстановлен из памяти, которая была перезаписана и т. Д.].

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

Разделение «чувствительных» и «не чувствительных» частей вашего приложения на отдельные процессы может стать еще одним способом обеспечения большей безопасности.

1

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

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

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