C++: обратные вызовы и события системного таймера во время каскада деструкторов
Предположим, что объектно-ориентированный проект предполагает, что объекты вызывают друг друга, а через некоторое время вызываемые объекты вызывают обратные вызовы инициирующих объектов (вызовы и обратные вызовы). Есть ли какое-то обещание, что при нормальном завершении программы при вызове деструкторов никакие системные таймеры не будут вызываться, и никакой объект не будет инициировать обратный вызов?
4 ответа
Существует довольно классная библиотека для обработки вызовов такого рода, и, конечно, это Boost.
Вот Boost.Signals2, с гарантией корректности даже в многопоточных приложениях:)
Обратите внимание, в частности, на использование boost::trackable
класс, так что уничтожение объектов автоматически делает недействительными вызовы до того, как они произойдут.
Примечание: Boost.Signals (его предок) имеет почти те же функции, но не является поточно-ориентированным
Нет, такой гарантии нет.
Вы должны написать свой код так, чтобы объекты не уничтожались, пока вы не закончили их использовать.
- Ускорение boost_lab_ptr может помочь избежать доступа к разрушенным объектам из обратных вызовов вообще, так что, вероятно, также во время завершения. При использовании этого все объекты, которые должны быть отозваны, нуждаются в shared_ptr.
- таймеры, вызывающие функции / обратные вызовы, обычно являются библиотеками более высокого уровня, поэтому зависит, поддерживают ли они функцию stopAllTimers(). Если у вас есть контроль над библиотекой, ее, вероятно, не так сложно реализовать, но вам все равно нужно знать, когда ее запускать.
Нет, обещаний нет.
Есть два способа справиться с этим:
Имейте функцию отмены регистрации, которую объект может вызвать при уничтожении, которая гарантирует, что никакие обратные вызовы не будут вызваны после его завершения -
CancelAllCallbacks()
или похожие.Имейте механизм слабой ссылки, такой как weak_ptr, который уже был упомянут, чтобы вызывать обратный вызов, только если сильная ссылка была успешно получена.
Обычно первого варианта достаточно, если обратные вызовы не могут быть запланированы или вызваны асинхронно - тогда у вас нет синхронного способа предотвратить обратный вызов, который уже запланирован для вызова или фактически вызывается сейчас (или несколько инструкций из сейчас) в другой теме.