[libcamera-devel] [PATCH 15/18] libcamera: object: Create parent-child relationships
Jacopo Mondi
jacopo at jmondi.org
Thu Aug 15 11:56:47 CEST 2019
Hi Laurent,
On Mon, Aug 12, 2019 at 03:46:39PM +0300, Laurent Pinchart wrote:
> Add a parent Object to Object instances, and track the parent-children
> relationships. Children are bound to the same thread as their parent,
> and moving an Object to a thread automatically moves all its children.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
> include/libcamera/object.h | 8 ++++-
> src/libcamera/include/thread.h | 2 ++
> src/libcamera/object.cpp | 65 ++++++++++++++++++++++++++++------
> src/libcamera/thread.cpp | 12 ++++++-
> 4 files changed, 74 insertions(+), 13 deletions(-)
>
> diff --git a/include/libcamera/object.h b/include/libcamera/object.h
> index 14b939a9bd3d..4a0a272b875a 100644
> --- a/include/libcamera/object.h
> +++ b/include/libcamera/object.h
> @@ -9,6 +9,7 @@
>
> #include <list>
> #include <memory>
> +#include <vector>
>
> #include <libcamera/bound_method.h>
>
> @@ -23,7 +24,7 @@ class Thread;
> class Object
> {
> public:
> - Object();
> + Object(Object *parent = nullptr);
> virtual ~Object();
>
> void postMessage(std::unique_ptr<Message> msg);
> @@ -42,6 +43,8 @@ public:
> Thread *thread() const { return thread_; }
> void moveToThread(Thread *thread);
>
> + Object *parent() const { return parent_; }
maybe const Object * ?
> +
> protected:
> virtual void message(Message *msg);
>
> @@ -58,6 +61,9 @@ private:
> void connect(SignalBase *signal);
> void disconnect(SignalBase *signal);
>
> + Object *parent_;
> + std::vector<Object *> children_;
> +
> Thread *thread_;
> std::list<SignalBase *> signals_;
> unsigned int pendingMessages_;
> diff --git a/src/libcamera/include/thread.h b/src/libcamera/include/thread.h
> index 630abb49534f..37edd4f5138b 100644
> --- a/src/libcamera/include/thread.h
> +++ b/src/libcamera/include/thread.h
> @@ -61,6 +61,8 @@ private:
> friend class ThreadMain;
>
> void moveObject(Object *object);
> + void moveObject(Object *object, ThreadData *currentData,
> + ThreadData *targetData);
>
> std::thread thread_;
> ThreadData *data_;
> diff --git a/src/libcamera/object.cpp b/src/libcamera/object.cpp
> index 7c68ec01f78c..57cd6fefe20f 100644
> --- a/src/libcamera/object.cpp
> +++ b/src/libcamera/object.cpp
> @@ -7,6 +7,8 @@
>
> #include <libcamera/object.h>
>
> +#include <algorithm>
> +
> #include <libcamera/signal.h>
>
> #include "log.h"
> @@ -21,6 +23,8 @@
>
> namespace libcamera {
>
> +LOG_DEFINE_CATEGORY(Object)
> +
> /**
> * \class Object
> * \brief Base object to support automatic signal disconnection
> @@ -29,10 +33,11 @@ namespace libcamera {
> * slots. By inheriting from Object, an object is automatically disconnected
> * from all connected signals when it gets destroyed.
> *
> - * Object instances are bound to the thread in which they're created. When a
> - * message is posted to an object, its handler will run in the object's thread.
> - * This allows implementing easy message passing between threads by inheriting
> - * from the Object class.
> + * Object instances are bound to the thread of their parent, or the thread in
> + * which they're created when they have no parent. When a message is posted to
> + * an object, its handler will run in the object's thread. This allows
> + * implementing easy message passing between threads by inheriting from the
> + * Object class.
> *
> * Object slots connected to signals will also run in the context of the
> * object's thread, regardless of whether the signal is emitted in the same or
> @@ -41,10 +46,20 @@ namespace libcamera {
> * \sa Message, Signal, Thread
> */
>
> -Object::Object()
> - : pendingMessages_(0)
> +/**
> + * \brief Construct an Object instance
> + * \param[in] parent The object parent
> + *
> + * The new Object instance is bound to the thread of its \a parent, or to the
> + * current thread if the \a parent is nullptr.
> + */
> +Object::Object(Object *parent)
> + : parent_(parent), pendingMessages_(0)
> {
> - thread_ = Thread::current();
> + thread_ = parent ? parent->thread() : Thread::current();
> +
> + if (parent)
> + parent->children_.push_back(this);
> }
>
> Object::~Object()
> @@ -54,6 +69,16 @@ Object::~Object()
>
> if (pendingMessages_)
> thread()->removeMessages(this);
> +
> + if (parent_) {
> + auto it = std::find(parent_->children_.begin(),
> + parent_->children_.end(), this);
> + ASSERT(it != parent_->children_.end());
> + parent_->children_.erase(it);
> + }
> +
> + for (auto child : children_)
> + child->parent_ = nullptr;
> }
>
> /**
> @@ -143,16 +168,19 @@ void Object::invokeMethod(BoundMethodBase *method, void *args)
> */
>
> /**
> - * \brief Move the object to a different thread
> + * \brief Move the object and all its children to a different thread
> * \param[in] thread The target thread
> *
> - * This method moves the object from the current thread to the new \a thread.
> - * It shall be called from the thread in which the object currently lives,
> - * otherwise the behaviour is undefined.
> + * This method moves the object and all its children from the current thread to
> + * the new \a thread. It shall be called from the thread in which the object
> + * currently lives, otherwise the behaviour is undefined.
> *
> * Before the object is moved, a Message::ThreadMoveMessage message is sent to
> * it. The message() method can be reimplement in derived classes to be notified
> * of the upcoming thread move and perform any required processing.
> + *
> + * Moving an object that has a parent is not allowed, and causes undefined
> + * behaviour.
> */
> void Object::moveToThread(Thread *thread)
> {
> @@ -161,6 +189,12 @@ void Object::moveToThread(Thread *thread)
> if (thread_ == thread)
> return;
>
> + if (parent_) {
> + LOG(Object, Error)
> + << "Moving object to thread with a parent is not permitted";
> + return;
> + }
> +
> notifyThreadMove();
>
> thread->moveObject(this);
> @@ -170,8 +204,17 @@ void Object::notifyThreadMove()
> {
> Message msg(Message::ThreadMoveMessage);
> sendMessage(&msg);
> +
> + for (auto child : children_)
> + child->notifyThreadMove();
> }
>
> +/**
> + * \fn Object::parent()
> + * \brief Retrieve the object's parent
> + * \return The object's parent
> + */
> +
> void Object::connect(SignalBase *signal)
> {
> signals_.push_back(signal);
> diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp
> index 24422f7b7bd0..872ad1bd9d69 100644
> --- a/src/libcamera/thread.cpp
> +++ b/src/libcamera/thread.cpp
> @@ -448,7 +448,7 @@ void Thread::dispatchMessages()
> }
>
> /**
> - * \brief Move an \a object to the thread
> + * \brief Move an \a object and all its children to the thread
> * \param[in] object The object
> */
> void Thread::moveObject(Object *object)
> @@ -460,6 +460,12 @@ void Thread::moveObject(Object *object)
> MutexLocker lockerTo(targetData->mutex_, std::defer_lock);
> std::lock(lockerFrom, lockerTo);
>
> + moveObject(object, currentData, targetData);
> +}
> +
> +void Thread::moveObject(Object *object, ThreadData *currentData,
> + ThreadData *targetData)
> +{
> /* Move pending messages to the message queue of the new thread. */
> if (object->pendingMessages_) {
> unsigned int movedMessages = 0;
> @@ -483,6 +489,10 @@ void Thread::moveObject(Object *object)
> }
>
> object->thread_ = this;
> +
> + /* Move all children. */
> + for (auto child : object->children_)
> + moveObject(child, currentData, targetData);
> }
>
> }; /* namespace libcamera */
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://lists.libcamera.org/pipermail/libcamera-devel/attachments/20190815/d9866b94/attachment.sig>
More information about the libcamera-devel
mailing list