libcamera: object: Add deleteLater() support
This commit adds support to schedule the deletion of an Object to the thread it is bound to (similar to [1]). An Object getting destroyed by a different thread is considered as a violation as per the libcamera threading model. This will be useful for an Object where its ownership is shared via shared pointers in different threads. If the thread which drops the last reference of the Object is a different thread, the destructors get called in that particular thread, not the one Object is bound to. Hence, in order to resolve this kind of situation, the creation of shared pointer can be accompanied by a custom deleter which in turns use deleteLater() to ensure the Object is destroyed in its own thread. [1] https://doc.qt.io/qt-5/qobject.html#deleteLater Signed-off-by: Umang Jain <email@uajain.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
3fe7c1cdb4
commit
9558886f7a
4 changed files with 53 additions and 0 deletions
|
@ -25,6 +25,7 @@ public:
|
||||||
None = 0,
|
None = 0,
|
||||||
InvokeMessage = 1,
|
InvokeMessage = 1,
|
||||||
ThreadMoveMessage = 2,
|
ThreadMoveMessage = 2,
|
||||||
|
DeferredDelete = 3,
|
||||||
UserMessage = 1000,
|
UserMessage = 1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@ public:
|
||||||
Object(Object *parent = nullptr);
|
Object(Object *parent = nullptr);
|
||||||
virtual ~Object();
|
virtual ~Object();
|
||||||
|
|
||||||
|
void deleteLater();
|
||||||
|
|
||||||
void postMessage(std::unique_ptr<Message> msg);
|
void postMessage(std::unique_ptr<Message> msg);
|
||||||
|
|
||||||
template<typename T, typename R, typename... FuncArgs, typename... Args,
|
template<typename T, typename R, typename... FuncArgs, typename... Args,
|
||||||
|
|
|
@ -49,6 +49,8 @@ std::atomic_uint Message::nextUserType_{ Message::UserMessage };
|
||||||
* \brief Asynchronous method invocation across threads
|
* \brief Asynchronous method invocation across threads
|
||||||
* \var Message::ThreadMoveMessage
|
* \var Message::ThreadMoveMessage
|
||||||
* \brief Object is being moved to a different thread
|
* \brief Object is being moved to a different thread
|
||||||
|
* \var Message::DeferredDelete
|
||||||
|
* \brief Object is scheduled for deletion
|
||||||
* \var Message::UserMessage
|
* \var Message::UserMessage
|
||||||
* \brief First value available for user-defined messages
|
* \brief First value available for user-defined messages
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -73,6 +73,10 @@ Object::Object(Object *parent)
|
||||||
* Deleting an Object automatically disconnects all signals from the Object's
|
* Deleting an Object automatically disconnects all signals from the Object's
|
||||||
* slots. All the Object's children are made orphan, but stay bound to their
|
* slots. All the Object's children are made orphan, but stay bound to their
|
||||||
* current thread.
|
* current thread.
|
||||||
|
*
|
||||||
|
* Object instances shall be destroyed from the thread they are bound to,
|
||||||
|
* otherwise undefined behaviour may occur. If deletion of an Object needs to
|
||||||
|
* be scheduled from a different thread, deleteLater() shall be used.
|
||||||
*/
|
*/
|
||||||
Object::~Object()
|
Object::~Object()
|
||||||
{
|
{
|
||||||
|
@ -98,6 +102,46 @@ Object::~Object()
|
||||||
child->parent_ = nullptr;
|
child->parent_ = 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<MyObject> createObject()
|
||||||
|
* {
|
||||||
|
* struct Deleter : std::default_delete<MyObject> {
|
||||||
|
* void operator()(MyObject *obj)
|
||||||
|
* {
|
||||||
|
* delete obj;
|
||||||
|
* }
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* MyObject *obj = new MyObject();
|
||||||
|
*
|
||||||
|
* return std::shared_ptr<MyObject>(obj, Deleter());
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* \context This function is \threadsafe.
|
||||||
|
*/
|
||||||
|
void Object::deleteLater()
|
||||||
|
{
|
||||||
|
postMessage(std::make_unique<Message>(Message::DeferredDelete));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Post a message to the object's thread
|
* \brief Post a message to the object's thread
|
||||||
* \param[in] msg The message
|
* \param[in] msg The message
|
||||||
|
@ -144,6 +188,10 @@ void Object::message(Message *msg)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Message::DeferredDelete:
|
||||||
|
delete this;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue