[libcamera-devel,v2,7/9] libcamera: object: Add connection type parameter to invokeMethod()

Message ID 20191028104913.14985-8-laurent.pinchart@ideasonboard.com
State Accepted
Headers show
Series
  • Add support for blocking method invocation
Related show

Commit Message

Laurent Pinchart Oct. 28, 2019, 10:49 a.m. UTC
From: Jacopo Mondi <jacopo@jmondi.org>

Allow specifying a different connection type than ConnectionTypeQueued
for Object::invokeMethod().

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 include/libcamera/object.h       |  5 ++---
 src/android/camera_proxy.cpp     |  3 ++-
 src/libcamera/event_notifier.cpp |  3 ++-
 src/libcamera/object.cpp         |  9 +++++----
 src/libcamera/timer.cpp          |  3 ++-
 test/object-invoke.cpp           | 14 ++++++++------
 6 files changed, 21 insertions(+), 16 deletions(-)

Comments

Niklas Söderlund Oct. 29, 2019, 2:49 p.m. UTC | #1
Hi Jacopo,

Thanks for your work.

On 2019-10-28 12:49:11 +0200, Laurent Pinchart wrote:
> From: Jacopo Mondi <jacopo@jmondi.org>
> 
> Allow specifying a different connection type than ConnectionTypeQueued
> for Object::invokeMethod().
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>

> ---
>  include/libcamera/object.h       |  5 ++---
>  src/android/camera_proxy.cpp     |  3 ++-
>  src/libcamera/event_notifier.cpp |  3 ++-
>  src/libcamera/object.cpp         |  9 +++++----
>  src/libcamera/timer.cpp          |  3 ++-
>  test/object-invoke.cpp           | 14 ++++++++------
>  6 files changed, 21 insertions(+), 16 deletions(-)
> 
> diff --git a/include/libcamera/object.h b/include/libcamera/object.h
> index 603a229288c2..91b56596c9db 100644
> --- a/include/libcamera/object.h
> +++ b/include/libcamera/object.h
> @@ -30,12 +30,11 @@ public:
>  	void postMessage(std::unique_ptr<Message> msg);
>  
>  	template<typename T, typename... Args, typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr>
> -	void invokeMethod(void (T::*func)(Args...), Args... args)
> +	void invokeMethod(void (T::*func)(Args...), ConnectionType type, Args... args)
>  	{
>  		T *obj = static_cast<T *>(this);
>  		BoundMethodBase *method =
> -			new BoundMemberMethod<T, Args...>(obj, this, func,
> -							  ConnectionTypeQueued);
> +			new BoundMemberMethod<T, Args...>(obj, this, func, type);
>  		void *pack = new typename BoundMemberMethod<T, Args...>::PackType{ args... };
>  
>  		method->activatePack(pack, true);
> diff --git a/src/android/camera_proxy.cpp b/src/android/camera_proxy.cpp
> index 4f5c0a024903..43e1e1c3af53 100644
> --- a/src/android/camera_proxy.cpp
> +++ b/src/android/camera_proxy.cpp
> @@ -187,6 +187,7 @@ int CameraProxy::processCaptureRequest(camera3_capture_request_t *request)
>  
>  void CameraProxy::threadRpcCall(ThreadRpc &rpcRequest)
>  {
> -	cameraDevice_->invokeMethod(&CameraDevice::call, &rpcRequest);
> +	cameraDevice_->invokeMethod(&CameraDevice::call, ConnectionTypeQueued,
> +				    &rpcRequest);
>  	rpcRequest.waitDelivery();
>  }
> diff --git a/src/libcamera/event_notifier.cpp b/src/libcamera/event_notifier.cpp
> index 687969b0a8d1..4326b0b413e2 100644
> --- a/src/libcamera/event_notifier.cpp
> +++ b/src/libcamera/event_notifier.cpp
> @@ -128,7 +128,8 @@ void EventNotifier::message(Message *msg)
>  	if (msg->type() == Message::ThreadMoveMessage) {
>  		if (enabled_) {
>  			setEnabled(false);
> -			invokeMethod(&EventNotifier::setEnabled, true);
> +			invokeMethod(&EventNotifier::setEnabled,
> +				     ConnectionTypeQueued, true);
>  		}
>  	}
>  
> diff --git a/src/libcamera/object.cpp b/src/libcamera/object.cpp
> index 509b2ebac537..db2c6f68fbc8 100644
> --- a/src/libcamera/object.cpp
> +++ b/src/libcamera/object.cpp
> @@ -139,14 +139,15 @@ void Object::message(Message *msg)
>  }
>  
>  /**
> - * \fn void Object::invokeMethod(void (T::*func)(Args...), Args... args)
> + * \fn void Object::invokeMethod()
>   * \brief Invoke a method asynchronously on an Object instance
>   * \param[in] func The object method to invoke
> + * \param[in] type Connection type for method invocation
>   * \param[in] args The method arguments
>   *
> - * This method invokes the member method \a func when control returns to the
> - * event loop of the object's thread. The method is executed in the object's
> - * thread with arguments \a args.
> + * This method invokes the member method \a func with arguments \a args, based
> + * on the connection \a type. Depending on the type, the method will be called
> + * synchronously in the same thread or asynchronously in the object's thread.
>   *
>   * Arguments \a args passed by value or reference are copied, while pointers
>   * are passed untouched. The caller shall ensure that any pointer argument
> diff --git a/src/libcamera/timer.cpp b/src/libcamera/timer.cpp
> index ddb20954afa7..4c68883204e8 100644
> --- a/src/libcamera/timer.cpp
> +++ b/src/libcamera/timer.cpp
> @@ -170,7 +170,8 @@ void Timer::message(Message *msg)
>  	if (msg->type() == Message::ThreadMoveMessage) {
>  		if (isRunning()) {
>  			unregisterTimer();
> -			invokeMethod(&Timer::registerTimer);
> +			invokeMethod(&Timer::registerTimer,
> +				     ConnectionTypeQueued);
>  		}
>  	}
>  
> diff --git a/test/object-invoke.cpp b/test/object-invoke.cpp
> index 37a274402e6d..f6ae2604db76 100644
> --- a/test/object-invoke.cpp
> +++ b/test/object-invoke.cpp
> @@ -64,10 +64,11 @@ protected:
>  		InvokedObject object;
>  
>  		/*
> -		 * Test that method invocation in the same thread goes through
> -		 * the event dispatcher.
> +		 * Test that queued method invocation in the same thread goes
> +		 * through the event dispatcher.
>  		 */
> -		object.invokeMethod(&InvokedObject::method, 42);
> +		object.invokeMethod(&InvokedObject::method,
> +				    ConnectionTypeQueued, 42);
>  
>  		if (object.status() != InvokedObject::NoCall) {
>  			cerr << "Method not invoked asynchronously" << endl;
> @@ -93,15 +94,16 @@ protected:
>  		}
>  
>  		/*
> -		 * Move the object to a thread and verify that the method is
> -		 * delivered in the correct thread.
> +		 * Move the object to a thread and verify that auto method
> +		 * invocation is delivered in the correct thread.
>  		 */
>  		object.reset();
>  		object.moveToThread(&thread_);
>  
>  		thread_.start();
>  
> -		object.invokeMethod(&InvokedObject::method, 42);
> +		object.invokeMethod(&InvokedObject::method,
> +				    ConnectionTypeAuto, 42);
>  		this_thread::sleep_for(chrono::milliseconds(100));
>  
>  		switch (object.status()) {
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel@lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel

Patch

diff --git a/include/libcamera/object.h b/include/libcamera/object.h
index 603a229288c2..91b56596c9db 100644
--- a/include/libcamera/object.h
+++ b/include/libcamera/object.h
@@ -30,12 +30,11 @@  public:
 	void postMessage(std::unique_ptr<Message> msg);
 
 	template<typename T, typename... Args, typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr>
-	void invokeMethod(void (T::*func)(Args...), Args... args)
+	void invokeMethod(void (T::*func)(Args...), ConnectionType type, Args... args)
 	{
 		T *obj = static_cast<T *>(this);
 		BoundMethodBase *method =
-			new BoundMemberMethod<T, Args...>(obj, this, func,
-							  ConnectionTypeQueued);
+			new BoundMemberMethod<T, Args...>(obj, this, func, type);
 		void *pack = new typename BoundMemberMethod<T, Args...>::PackType{ args... };
 
 		method->activatePack(pack, true);
diff --git a/src/android/camera_proxy.cpp b/src/android/camera_proxy.cpp
index 4f5c0a024903..43e1e1c3af53 100644
--- a/src/android/camera_proxy.cpp
+++ b/src/android/camera_proxy.cpp
@@ -187,6 +187,7 @@  int CameraProxy::processCaptureRequest(camera3_capture_request_t *request)
 
 void CameraProxy::threadRpcCall(ThreadRpc &rpcRequest)
 {
-	cameraDevice_->invokeMethod(&CameraDevice::call, &rpcRequest);
+	cameraDevice_->invokeMethod(&CameraDevice::call, ConnectionTypeQueued,
+				    &rpcRequest);
 	rpcRequest.waitDelivery();
 }
diff --git a/src/libcamera/event_notifier.cpp b/src/libcamera/event_notifier.cpp
index 687969b0a8d1..4326b0b413e2 100644
--- a/src/libcamera/event_notifier.cpp
+++ b/src/libcamera/event_notifier.cpp
@@ -128,7 +128,8 @@  void EventNotifier::message(Message *msg)
 	if (msg->type() == Message::ThreadMoveMessage) {
 		if (enabled_) {
 			setEnabled(false);
-			invokeMethod(&EventNotifier::setEnabled, true);
+			invokeMethod(&EventNotifier::setEnabled,
+				     ConnectionTypeQueued, true);
 		}
 	}
 
diff --git a/src/libcamera/object.cpp b/src/libcamera/object.cpp
index 509b2ebac537..db2c6f68fbc8 100644
--- a/src/libcamera/object.cpp
+++ b/src/libcamera/object.cpp
@@ -139,14 +139,15 @@  void Object::message(Message *msg)
 }
 
 /**
- * \fn void Object::invokeMethod(void (T::*func)(Args...), Args... args)
+ * \fn void Object::invokeMethod()
  * \brief Invoke a method asynchronously on an Object instance
  * \param[in] func The object method to invoke
+ * \param[in] type Connection type for method invocation
  * \param[in] args The method arguments
  *
- * This method invokes the member method \a func when control returns to the
- * event loop of the object's thread. The method is executed in the object's
- * thread with arguments \a args.
+ * This method invokes the member method \a func with arguments \a args, based
+ * on the connection \a type. Depending on the type, the method will be called
+ * synchronously in the same thread or asynchronously in the object's thread.
  *
  * Arguments \a args passed by value or reference are copied, while pointers
  * are passed untouched. The caller shall ensure that any pointer argument
diff --git a/src/libcamera/timer.cpp b/src/libcamera/timer.cpp
index ddb20954afa7..4c68883204e8 100644
--- a/src/libcamera/timer.cpp
+++ b/src/libcamera/timer.cpp
@@ -170,7 +170,8 @@  void Timer::message(Message *msg)
 	if (msg->type() == Message::ThreadMoveMessage) {
 		if (isRunning()) {
 			unregisterTimer();
-			invokeMethod(&Timer::registerTimer);
+			invokeMethod(&Timer::registerTimer,
+				     ConnectionTypeQueued);
 		}
 	}
 
diff --git a/test/object-invoke.cpp b/test/object-invoke.cpp
index 37a274402e6d..f6ae2604db76 100644
--- a/test/object-invoke.cpp
+++ b/test/object-invoke.cpp
@@ -64,10 +64,11 @@  protected:
 		InvokedObject object;
 
 		/*
-		 * Test that method invocation in the same thread goes through
-		 * the event dispatcher.
+		 * Test that queued method invocation in the same thread goes
+		 * through the event dispatcher.
 		 */
-		object.invokeMethod(&InvokedObject::method, 42);
+		object.invokeMethod(&InvokedObject::method,
+				    ConnectionTypeQueued, 42);
 
 		if (object.status() != InvokedObject::NoCall) {
 			cerr << "Method not invoked asynchronously" << endl;
@@ -93,15 +94,16 @@  protected:
 		}
 
 		/*
-		 * Move the object to a thread and verify that the method is
-		 * delivered in the correct thread.
+		 * Move the object to a thread and verify that auto method
+		 * invocation is delivered in the correct thread.
 		 */
 		object.reset();
 		object.moveToThread(&thread_);
 
 		thread_.start();
 
-		object.invokeMethod(&InvokedObject::method, 42);
+		object.invokeMethod(&InvokedObject::method,
+				    ConnectionTypeAuto, 42);
 		this_thread::sleep_for(chrono::milliseconds(100));
 
 		switch (object.status()) {