[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