diff --git a/include/libcamera/internal/message.h b/include/libcamera/internal/message.h index 92ea64a5d..f1b133bfb 100644 --- a/include/libcamera/internal/message.h +++ b/include/libcamera/internal/message.h @@ -25,6 +25,7 @@ public: None = 0, InvokeMessage = 1, ThreadMoveMessage = 2, + DeferredDelete = 3, UserMessage = 1000, }; diff --git a/include/libcamera/object.h b/include/libcamera/object.h index 9a3dd0702..a1882f05f 100644 --- a/include/libcamera/object.h +++ b/include/libcamera/object.h @@ -27,6 +27,8 @@ public: Object(Object *parent = nullptr); virtual ~Object(); + void deleteLater(); + void postMessage(std::unique_ptr msg); templateparent_ = nullptr; } +/** + * \brief Schedule deletion of the instance in the thread it belongs to + * + * This function schedules deletion of the Object when control returns to the + * event loop that the object belongs to. This ensures the object is destroyed + * from the right context, as required by the libcamera threading model. + * + * If this function is called before the thread's event loop is started, the + * object will be deleted when the event loop starts. + * + * Deferred deletion can be used to control the destruction context with shared + * pointers. An object managed with shared pointers is deleted when the last + * reference is destroyed, which makes difficult to ensure through software + * design which context the deletion will take place in. With a custom deleter + * for the shared pointer using deleteLater(), the deletion can be guaranteed to + * happen in the thread the object is bound to. + * + * \code{.cpp} + * std::shared_ptr createObject() + * { + * struct Deleter : std::default_delete { + * void operator()(MyObject *obj) + * { + * delete obj; + * } + * }; + * + * MyObject *obj = new MyObject(); + * + * return std::shared_ptr(obj, Deleter()); + * } + * \endcode + * + * \context This function is \threadsafe. + */ +void Object::deleteLater() +{ + postMessage(std::make_unique(Message::DeferredDelete)); +} + /** * \brief Post a message to the object's thread * \param[in] msg The message @@ -144,6 +188,10 @@ void Object::message(Message *msg) break; } + case Message::DeferredDelete: + delete this; + break; + default: break; }