Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Экспериментальная альтернатива — двухфазная семантика разрушения. Вместо деструктора пишутся два метода release и deferred — release выполняется всегда в самом конце, deferred выполняется перед release и только в случае если не летит исключение. В итоге пример выше переписывается в: EP>
по теме. _NN>Стандартизировать это еще не собираются в C++17
std::uncaught_exceptions уже в текущем Draft'е — 18.8.4.
Но для кидающих деструкторов его всё же следует использовать с осторожностью. Дело в том что объект созданный в одном scope может переехать в другой — в котором будет другое начальное значение uncaught_exceptions.
Для реализаций scope(failure) и scope(success) — это не проблема, так как их объекты-guard'ы живут в одном scope.
Здравствуйте, Vlad_SP, Вы писали:
CEM>> К примеру, файл полностью записан и закрыт.
V_S>В файл записалась только половина данных, дальше кончилось место на диске. V_S>На сервер в Тимбукту передана только половина данных, дальше пьяный экскаваторщик Вася в Мухосранске порвал магистральный кабель. V_S>И так далее....
Ну и нормально. Файл полностью записать и закрыт? Нет — объект отправляем в пул. Не вижу проблем.
Здравствуйте, landerhigh, Вы писали:
L>Всем такие события поздновато разруливать в деструкторе. L>В принципе можно, но под этим деструктором должна быть еще куча уровней, которые умеют это разруливать сами.
Ну вот я для того пункт 2 и придумал, чтобы это был и деструктор и не наш, т.е. у нашего объекта ещё было время сделать корректно все свои дела перед своим деструктором. Вообще мне такая схема кажется кривой и избыточной, но больше пока ничего не придумал.
по теме. _NN>>Стандартизировать это еще не собираются в C++17
EP>std::uncaught_exceptions уже в текущем Draft'е — 18.8.4.
Это в курсе.
Я про человечный синтаксис для TWO_STAGE_DESTRUCTOR_DEFERRED, TWO_STAGE_DESTRUCTOR_RELEASE.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Альтернативный вариант, озвученный в статье, это игнорировать все кроме первого исключения.
Ну это просто праздник какой-то!
EP>Думаю можно вызывать глобальный пользовательский callback для игнорируемых исключений.
Так его и так никто не мешает сделать прямо сейчас
L>>Но у меня другой вопрос — а что с объектом-то? Вот выкинул он исключение на полпути деструктора. И стал зомби. Вернуть к жизни его нельзя. Добить? Как? Разрешать рекуррентный вызов деструктора, чтобы наверняка добить? Так это ничем не отличается от цепочки cleanup() — delete. L>>Или принять ограничения, что исключение в деструкторе — чисто информационное и объект, выбросивший его, гаратированно убит? EP>Например в само исключение можно запаковывать все внутренности объекта. То есть например file handle будет внутри объекта исключения.
Это же нарушает инкапсуляцию. Да и вся сила RAII в том, что клиенты не обязаны знать, что под капотом объекта там что-то такое происходит. А тут — красиво заворачиваем кишочки объекта в праздничную упаковку и перебрасываем ее через забор, авось кто поймает
Здравствуйте, T4r4sB, Вы писали:
TB>В деструкторе записывать успешность результата во внешнюю переменную (ссылка на которую даётся в конструкторе). Потом проверять эту переменную.
Можно даже пойти дальше и сделать ленивый проброс исключений.
class A
{
//.....
~A() {
if(!m_file.save())
LASY_THROW(FileSaveException());
}
};
///...........
{
A a;
// do some stuff
// ....
}
RETHROW();
Но это, конечно, тоже полумера и не всегда уместная.
Здравствуйте, landerhigh, Вы писали:
EP>>Альтернативный вариант, озвученный в статье, это игнорировать все кроме первого исключения. L>Ну это просто праздник какой-то!
Всяко лучше чем std::terminate.
EP>>Думаю можно вызывать глобальный пользовательский callback для игнорируемых исключений. L>Так его и так никто не мешает сделать прямо сейчас
Сейчас игнорируются (программистами) все исключения в деструкторах, и нет общего надёжного способа узнать когда можно кидать исключение, а когда будет std::terminate.
В этом же варианте по сути вместо std::terminate будет вызван пользовательский callback.
L>>>Но у меня другой вопрос — а что с объектом-то? Вот выкинул он исключение на полпути деструктора. И стал зомби. Вернуть к жизни его нельзя. Добить? Как? Разрешать рекуррентный вызов деструктора, чтобы наверняка добить? Так это ничем не отличается от цепочки cleanup() — delete. L>>>Или принять ограничения, что исключение в деструкторе — чисто информационное и объект, выбросивший его, гаратированно убит? EP>>Например в само исключение можно запаковывать все внутренности объекта. То есть например file handle будет внутри объекта исключения. L>Это же нарушает инкапсуляцию. Да и вся сила RAII в том, что клиенты не обязаны знать, что под капотом объекта там что-то такое происходит. А тут — красиво заворачиваем кишочки объекта в праздничную упаковку и перебрасываем ее через забор, авось кто поймает
Я описывал чисто технические внутренности, в реальности этот кидаемый file handle может быть завёрнут в полноценную RAII обёртку, которая автоматически закроет файл даже если наверху это исключение не обработается специальным образом (например будут ловить только базовое std::exception).
То есть мой поинт не в том что нужно кидаться голыми кишками, а в том что нет проблемы в том что мы находимся в деструкторе объекта File, и после выброса исключения он прекратит своё существование. Мы можем запоковать всё необходимое во внутрь исключения, тем самым продлив время жизни необходимых ресурсов на время раскрутки стэка — а уже наверху смогут принять конкретные решения.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
L>>Ну это просто праздник какой-то!
EP>Всяко лучше чем std::terminate.
Чем же лучше? Что вобще может выдать ошибку в деструкторе? "Не могу вернуть память"? Бугага. "Ниасилил записать"? По логике, если это происходит в деструкторе, то обычно это значит, что "ну и чорд с ним". А вот если вовсе не "чорд с ним", то terminate — наше фсио!
Я, конечно, знаю примеры, когда деструктор вызывал такую длинную цепочку вызовов, что из нее могло прилететь все, что угодно. Но это вовсе не значит, что нужно так делать. И то, что это спрятано внутри вызова деструктора, как бы намекает, что код, использующий этот класс, вовсе не обязан быть в курсе всей происходящей за кулисами кухни.
EP>Сейчас игнорируются (программистами) все исключения в деструкторах, и нет общего надёжного способа узнать когда можно кидать исключение, а когда будет std::terminate.
В принципе, в каждом таком треде все это сводится к одному-единственному примеру. "Класс закрывает файл в деструкторе, а вдруг закрытие файла обломается". Я же считаю, что это сферическое программирование в вакууме. Если при закрытии файла выскочила ошибка, то что-то сделать, чтобы исправить эту конкретную ошибку, пользовательский код уже вряд ли сможет.
EP>В этом же варианте по сути вместо std::terminate будет вызван пользовательский callback.
L>>>>Но у меня другой вопрос — а что с объектом-то? Вот выкинул он исключение на полпути деструктора. И стал зомби. Вернуть к жизни его нельзя. Добить? Как? Разрешать рекуррентный вызов деструктора, чтобы наверняка добить? Так это ничем не отличается от цепочки cleanup() — delete. L>>>>Или принять ограничения, что исключение в деструкторе — чисто информационное и объект, выбросивший его, гаратированно убит? EP>>>Например в само исключение можно запаковывать все внутренности объекта. То есть например file handle будет внутри объекта исключения.
Не-не-не, что с оригинальным объектом? Вот на полпути в деструкторе вылетает исключение. Оно делает невозможным как продолжение выполнения кода деструктора, так и собственно освобождение остальных ресурсов объекта. То есть логика завершения работы объекта идет побоку, а там может быть чего понавороченнее, чем просто "закрыть файл".
EP>То есть мой поинт не в том что нужно кидаться голыми кишками, а в том что нет проблемы в том что мы находимся в деструкторе объекта File, и после выброса исключения он прекратит своё существование. Мы можем запоковать всё необходимое во внутрь исключения, тем самым продлив время жизни необходимых ресурсов на время раскрутки стэка — а уже наверху смогут принять конкретные решения.
Что-то франкенштейн какой-то получается, честное слово. Одна нога тут, другая там, а голова вообще в Филадельфии
Как раз появилась статья на хабре на эту тему — http://habrahabr.ru/post/270545/, как я понимаю написана по мотивам рассуждений Александреску на эту тему, решил здесь оставить ссылку на случай если кто-то еще будет чимтать этот тред когда-то потом.)