[libcamera-devel,1/2] libcamera: thread: Support timeout in wait() function

Message ID 20200123025520.12149-1-laurent.pinchart@ideasonboard.com
State Superseded
Headers show
Series
  • [libcamera-devel,1/2] libcamera: thread: Support timeout in wait() function
Related show

Commit Message

Laurent Pinchart Jan. 23, 2020, 2:55 a.m. UTC
Add a parameter to the Thread::wait() function to wait with a timeout.
The delay value waits forever.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 src/libcamera/include/thread.h |  4 +++-
 src/libcamera/thread.cpp       | 28 +++++++++++++++++++++++++---
 2 files changed, 28 insertions(+), 4 deletions(-)

Comments

Kieran Bingham Jan. 23, 2020, 10:10 a.m. UTC | #1
Hi Laurent

On 23/01/2020 02:55, Laurent Pinchart wrote:
> Add a parameter to the Thread::wait() function to wait with a timeout.
> The delay value waits forever.

I presume you mean

"No delay value waits forever"
 or
"The delay value utils::duration::max() waits forever."


With that fixed up,

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  src/libcamera/include/thread.h |  4 +++-
>  src/libcamera/thread.cpp       | 28 +++++++++++++++++++++++++---
>  2 files changed, 28 insertions(+), 4 deletions(-)
> 
> diff --git a/src/libcamera/include/thread.h b/src/libcamera/include/thread.h
> index 819a9879ac56..d700f111a3ae 100644
> --- a/src/libcamera/include/thread.h
> +++ b/src/libcamera/include/thread.h
> @@ -14,6 +14,8 @@
>  
>  #include <libcamera/signal.h>
>  
> +#include "utils.h"
> +
>  namespace libcamera {
>  
>  class EventDispatcher;
> @@ -33,7 +35,7 @@ public:
>  
>  	void start();
>  	void exit(int code = 0);
> -	void wait();
> +	bool wait(utils::duration duration = utils::duration::max());
>  
>  	bool isRunning();
>  
> diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp
> index fe32cd677596..22ab41f847db 100644
> --- a/src/libcamera/thread.cpp
> +++ b/src/libcamera/thread.cpp
> @@ -8,6 +8,7 @@
>  #include "thread.h"
>  
>  #include <atomic>
> +#include <condition_variable>
>  #include <list>
>  #include <unistd.h>
>  #include <sys/syscall.h>
> @@ -71,6 +72,7 @@ private:
>  
>  	std::atomic<EventDispatcher *> dispatcher_;
>  
> +	std::condition_variable cv_;
>  	std::atomic<bool> exit_;
>  	int exitCode_;
>  
> @@ -248,6 +250,7 @@ void Thread::finishThread()
>  	data_->mutex_.unlock();
>  
>  	finished.emit(this);
> +	data_->cv_.notify_all();
>  }
>  
>  /**
> @@ -274,14 +277,33 @@ void Thread::exit(int code)
>  
>  /**
>   * \brief Wait for the thread to finish
> + * \param[in] duration Maximum wait duration
>   *
> - * This method waits until the thread finishes, or returns immediately if the
> - * thread is not running.
> + * This function waits until the thread finishes or the \a duration has
> + * elapsed, whichever happens first. If \a duration is equal to
> + * utils::duration::max(), the wait never times out. If the thread is not
> + * running the function returns immediately.
> + *
> + * \return True if the thread has finished, or false if the wait timed out
>   */
> -void Thread::wait()
> +bool Thread::wait(utils::duration duration)
>  {
> +	bool timeout = false;
> +
> +	{
> +		MutexLocker locker(data_->mutex_);
> +
> +		if (duration == utils::duration::max())
> +			data_->cv_.wait(locker, [&]() { return !data_->running_; });
> +		else
> +			timeout = !data_->cv_.wait_for(locker, duration,
> +						       [&]() { return !data_->running_; });
> +	}
> +
>  	if (thread_.joinable())
>  		thread_.join();
> +
> +	return timeout;
>  }
>  
>  /**
>
Niklas Söderlund Feb. 10, 2020, 9:09 p.m. UTC | #2
Hi Laurent,

Thanks for your patch.

On 2020-01-23 04:55:19 +0200, Laurent Pinchart wrote:
> Add a parameter to the Thread::wait() function to wait with a timeout.
> The delay value waits forever.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

With the commit message fixed as pointer out by Kieran,

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

> ---
>  src/libcamera/include/thread.h |  4 +++-
>  src/libcamera/thread.cpp       | 28 +++++++++++++++++++++++++---
>  2 files changed, 28 insertions(+), 4 deletions(-)
> 
> diff --git a/src/libcamera/include/thread.h b/src/libcamera/include/thread.h
> index 819a9879ac56..d700f111a3ae 100644
> --- a/src/libcamera/include/thread.h
> +++ b/src/libcamera/include/thread.h
> @@ -14,6 +14,8 @@
>  
>  #include <libcamera/signal.h>
>  
> +#include "utils.h"
> +
>  namespace libcamera {
>  
>  class EventDispatcher;
> @@ -33,7 +35,7 @@ public:
>  
>  	void start();
>  	void exit(int code = 0);
> -	void wait();
> +	bool wait(utils::duration duration = utils::duration::max());
>  
>  	bool isRunning();
>  
> diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp
> index fe32cd677596..22ab41f847db 100644
> --- a/src/libcamera/thread.cpp
> +++ b/src/libcamera/thread.cpp
> @@ -8,6 +8,7 @@
>  #include "thread.h"
>  
>  #include <atomic>
> +#include <condition_variable>
>  #include <list>
>  #include <unistd.h>
>  #include <sys/syscall.h>
> @@ -71,6 +72,7 @@ private:
>  
>  	std::atomic<EventDispatcher *> dispatcher_;
>  
> +	std::condition_variable cv_;
>  	std::atomic<bool> exit_;
>  	int exitCode_;
>  
> @@ -248,6 +250,7 @@ void Thread::finishThread()
>  	data_->mutex_.unlock();
>  
>  	finished.emit(this);
> +	data_->cv_.notify_all();
>  }
>  
>  /**
> @@ -274,14 +277,33 @@ void Thread::exit(int code)
>  
>  /**
>   * \brief Wait for the thread to finish
> + * \param[in] duration Maximum wait duration
>   *
> - * This method waits until the thread finishes, or returns immediately if the
> - * thread is not running.
> + * This function waits until the thread finishes or the \a duration has
> + * elapsed, whichever happens first. If \a duration is equal to
> + * utils::duration::max(), the wait never times out. If the thread is not
> + * running the function returns immediately.
> + *
> + * \return True if the thread has finished, or false if the wait timed out
>   */
> -void Thread::wait()
> +bool Thread::wait(utils::duration duration)
>  {
> +	bool timeout = false;
> +
> +	{
> +		MutexLocker locker(data_->mutex_);
> +
> +		if (duration == utils::duration::max())
> +			data_->cv_.wait(locker, [&]() { return !data_->running_; });
> +		else
> +			timeout = !data_->cv_.wait_for(locker, duration,
> +						       [&]() { return !data_->running_; });
> +	}
> +
>  	if (thread_.joinable())
>  		thread_.join();
> +
> +	return timeout;
>  }
>  
>  /**
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel@lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel

Patch

diff --git a/src/libcamera/include/thread.h b/src/libcamera/include/thread.h
index 819a9879ac56..d700f111a3ae 100644
--- a/src/libcamera/include/thread.h
+++ b/src/libcamera/include/thread.h
@@ -14,6 +14,8 @@ 
 
 #include <libcamera/signal.h>
 
+#include "utils.h"
+
 namespace libcamera {
 
 class EventDispatcher;
@@ -33,7 +35,7 @@  public:
 
 	void start();
 	void exit(int code = 0);
-	void wait();
+	bool wait(utils::duration duration = utils::duration::max());
 
 	bool isRunning();
 
diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp
index fe32cd677596..22ab41f847db 100644
--- a/src/libcamera/thread.cpp
+++ b/src/libcamera/thread.cpp
@@ -8,6 +8,7 @@ 
 #include "thread.h"
 
 #include <atomic>
+#include <condition_variable>
 #include <list>
 #include <unistd.h>
 #include <sys/syscall.h>
@@ -71,6 +72,7 @@  private:
 
 	std::atomic<EventDispatcher *> dispatcher_;
 
+	std::condition_variable cv_;
 	std::atomic<bool> exit_;
 	int exitCode_;
 
@@ -248,6 +250,7 @@  void Thread::finishThread()
 	data_->mutex_.unlock();
 
 	finished.emit(this);
+	data_->cv_.notify_all();
 }
 
 /**
@@ -274,14 +277,33 @@  void Thread::exit(int code)
 
 /**
  * \brief Wait for the thread to finish
+ * \param[in] duration Maximum wait duration
  *
- * This method waits until the thread finishes, or returns immediately if the
- * thread is not running.
+ * This function waits until the thread finishes or the \a duration has
+ * elapsed, whichever happens first. If \a duration is equal to
+ * utils::duration::max(), the wait never times out. If the thread is not
+ * running the function returns immediately.
+ *
+ * \return True if the thread has finished, or false if the wait timed out
  */
-void Thread::wait()
+bool Thread::wait(utils::duration duration)
 {
+	bool timeout = false;
+
+	{
+		MutexLocker locker(data_->mutex_);
+
+		if (duration == utils::duration::max())
+			data_->cv_.wait(locker, [&]() { return !data_->running_; });
+		else
+			timeout = !data_->cv_.wait_for(locker, duration,
+						       [&]() { return !data_->running_; });
+	}
+
 	if (thread_.joinable())
 		thread_.join();
+
+	return timeout;
 }
 
 /**