[libcamera-devel,v3,1/3] libcamera: thread: Support selective message dispatch to thread

Message ID 20200731133947.84258-2-email@uajain.com
State Accepted
Headers show
Series
  • Add Object::deleteLater() support
Related show

Commit Message

Umang Jain July 31, 2020, 1:39 p.m. UTC
Extend the current dispatchMessages() to support dispatching of
selective messsages according to the Message::Type passed in
the function argument. dispatchMessages() can now be called
explicitly to force deliver selected type's message to the
thread for processing (typically when event loop is not
running).

Signed-off-by: Umang Jain <email@uajain.com>
---
 include/libcamera/internal/thread.h |  3 ++-
 src/libcamera/thread.cpp            | 30 ++++++++++++++++++++---------
 2 files changed, 23 insertions(+), 10 deletions(-)

Comments

Laurent Pinchart July 31, 2020, 2:22 p.m. UTC | #1
Hi Umang,

Thank you for the patch.

On Fri, Jul 31, 2020 at 01:39:53PM +0000, Umang Jain wrote:
> Extend the current dispatchMessages() to support dispatching of
> selective messsages according to the Message::Type passed in
> the function argument. dispatchMessages() can now be called
> explicitly to force deliver selected type's message to the
> thread for processing (typically when event loop is not
> running).
> 
> Signed-off-by: Umang Jain <email@uajain.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  include/libcamera/internal/thread.h |  3 ++-
>  src/libcamera/thread.cpp            | 30 ++++++++++++++++++++---------
>  2 files changed, 23 insertions(+), 10 deletions(-)
> 
> diff --git a/include/libcamera/internal/thread.h b/include/libcamera/internal/thread.h
> index 7b59e58..f6367a8 100644
> --- a/include/libcamera/internal/thread.h
> +++ b/include/libcamera/internal/thread.h
> @@ -14,6 +14,7 @@
>  
>  #include <libcamera/signal.h>
>  
> +#include "libcamera/internal/message.h"
>  #include "libcamera/internal/utils.h"
>  
>  namespace libcamera {
> @@ -47,7 +48,7 @@ public:
>  	EventDispatcher *eventDispatcher();
>  	void setEventDispatcher(std::unique_ptr<EventDispatcher> dispatcher);
>  
> -	void dispatchMessages();
> +	void dispatchMessages(Message::Type type = Message::Type::None);
>  
>  protected:
>  	int exec();
> diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp
> index d1750d7..7e318d9 100644
> --- a/src/libcamera/thread.cpp
> +++ b/src/libcamera/thread.cpp
> @@ -552,25 +552,37 @@ void Thread::removeMessages(Object *receiver)
>  }
>  
>  /**
> - * \brief Dispatch all posted messages for this thread
> + * \brief Dispatch posted messages for this thread
> + * \param[in] type The message type
> + *
> + * This function immediately dispatches all the messages previously posted for
> + * this thread with postMessage() that match the message \a type. If the \a type
> + * is Message::Type::None, all messages are dispatched.
>   */
> -void Thread::dispatchMessages()
> +void Thread::dispatchMessages(Message::Type type)
>  {
>  	MutexLocker locker(data_->messages_.mutex_);
>  
> -	while (!data_->messages_.list_.empty()) {
> -		std::unique_ptr<Message> msg = std::move(data_->messages_.list_.front());
> -		data_->messages_.list_.pop_front();
> -		if (!msg)
> +	std::list<std::unique_ptr<Message>> &messages = data_->messages_.list_;
> +
> +	for (auto iter = messages.begin(); iter != messages.end(); ) {
> +		std::unique_ptr<Message> &msg = *iter;
> +
> +		if (!msg || (type != Message::Type::None && msg->type() != type)) {
> +			++iter;
>  			continue;
> +		}
>  
> -		Object *receiver = msg->receiver_;
> -		ASSERT(data_ == receiver->thread()->data_);
> +		std::unique_ptr<Message> message = std::move(msg);
> +		iter = data_->messages_.list_.erase(iter);
>  
> +		Object *receiver = message->receiver_;
> +		ASSERT(data_ == receiver->thread()->data_);
>  		receiver->pendingMessages_--;
>  
>  		locker.unlock();
> -		receiver->message(msg.get());
> +		receiver->message(message.get());
> +		message.reset();
>  		locker.lock();
>  	}
>  }

Patch

diff --git a/include/libcamera/internal/thread.h b/include/libcamera/internal/thread.h
index 7b59e58..f6367a8 100644
--- a/include/libcamera/internal/thread.h
+++ b/include/libcamera/internal/thread.h
@@ -14,6 +14,7 @@ 
 
 #include <libcamera/signal.h>
 
+#include "libcamera/internal/message.h"
 #include "libcamera/internal/utils.h"
 
 namespace libcamera {
@@ -47,7 +48,7 @@  public:
 	EventDispatcher *eventDispatcher();
 	void setEventDispatcher(std::unique_ptr<EventDispatcher> dispatcher);
 
-	void dispatchMessages();
+	void dispatchMessages(Message::Type type = Message::Type::None);
 
 protected:
 	int exec();
diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp
index d1750d7..7e318d9 100644
--- a/src/libcamera/thread.cpp
+++ b/src/libcamera/thread.cpp
@@ -552,25 +552,37 @@  void Thread::removeMessages(Object *receiver)
 }
 
 /**
- * \brief Dispatch all posted messages for this thread
+ * \brief Dispatch posted messages for this thread
+ * \param[in] type The message type
+ *
+ * This function immediately dispatches all the messages previously posted for
+ * this thread with postMessage() that match the message \a type. If the \a type
+ * is Message::Type::None, all messages are dispatched.
  */
-void Thread::dispatchMessages()
+void Thread::dispatchMessages(Message::Type type)
 {
 	MutexLocker locker(data_->messages_.mutex_);
 
-	while (!data_->messages_.list_.empty()) {
-		std::unique_ptr<Message> msg = std::move(data_->messages_.list_.front());
-		data_->messages_.list_.pop_front();
-		if (!msg)
+	std::list<std::unique_ptr<Message>> &messages = data_->messages_.list_;
+
+	for (auto iter = messages.begin(); iter != messages.end(); ) {
+		std::unique_ptr<Message> &msg = *iter;
+
+		if (!msg || (type != Message::Type::None && msg->type() != type)) {
+			++iter;
 			continue;
+		}
 
-		Object *receiver = msg->receiver_;
-		ASSERT(data_ == receiver->thread()->data_);
+		std::unique_ptr<Message> message = std::move(msg);
+		iter = data_->messages_.list_.erase(iter);
 
+		Object *receiver = message->receiver_;
+		ASSERT(data_ == receiver->thread()->data_);
 		receiver->pendingMessages_--;
 
 		locker.unlock();
-		receiver->message(msg.get());
+		receiver->message(message.get());
+		message.reset();
 		locker.lock();
 	}
 }