Simplify the implementation of TaskRunner.
TestRunner used to hold the std::thread pointer and
a pointer to a boolean flag. Simplify them:
* std::thread* is not needed because detach() allows
the thread to run in background
* bool* is not needed; use a non-callable std::function
to indicate end of queue.
* Use std::shared_ptr instead of raw pointer for mQueue
to avoid weird pointer ownership management.
Test: libhidl_test
Test: hidl_test
Test: boots
Change-Id: I8fe7a6285bc537408ed559499951c17219e0df7f
diff --git a/base/TaskRunner.cpp b/base/TaskRunner.cpp
index 78add4c..cd1df05 100644
--- a/base/TaskRunner.cpp
+++ b/base/TaskRunner.cpp
@@ -22,26 +22,20 @@
namespace details {
TaskRunner::TaskRunner() {
- bool *running = mRunning = new bool();
- SynchronizedQueue<std::function<void(void)>> *q
- = mQueue = new SynchronizedQueue<std::function<void(void)>>();
- mThread = new std::thread([running, q] {
- *running = true;
- while (*running) {
- (q->wait_pop())();
+ mQueue = std::make_shared<SynchronizedQueue<Task>>();
+
+ // Allow the thread to continue running in background;
+ // TaskRunner do not care about the std::thread object.
+ std::thread{[q = mQueue] {
+ Task nextTask;
+ while (!!(nextTask = q->wait_pop())) {
+ nextTask();
}
- delete q;
- delete running;
- });
+ }}.detach();
}
+
TaskRunner::~TaskRunner() {
- bool *running = mRunning;
- std::thread *t = mThread;
- mThread->detach();
- mQueue->push([running, t] {
- *running = false;
- delete t;
- });
+ mQueue->push(nullptr);
}
} // namespace details
diff --git a/base/include/hidl/TaskRunner.h b/base/include/hidl/TaskRunner.h
index 7d340c7..b6e9a95 100644
--- a/base/include/hidl/TaskRunner.h
+++ b/base/include/hidl/TaskRunner.h
@@ -17,6 +17,7 @@
#define ANDROID_HIDL_TASK_RUNNER_H
#include "SynchronizedQueue.h"
+#include <memory>
#include <thread>
namespace android {
@@ -25,28 +26,28 @@
/*
* A background infinite loop that runs the Tasks push()'ed.
- * Just a simple single-threaded thread pool.
+ * Equivalent to a simple single-threaded Looper.
*/
class TaskRunner {
public:
+ using Task = std::function<void(void)>;
/* Kicks off the loop immediately. */
TaskRunner();
/*
- * Detaches the background thread and return immediately.
- * Tasks in the queue will continue to be done sequentially, and _after_
- * all tasks are done, the background thread releases the resources
- * (the queue, the std::thread object, etc.)
+ * Notify the background thread to terminate and return immediately.
+ * Tasks in the queue will continue to be done sequentially in background
+ * until all tasks are finished.
*/
~TaskRunner();
/*
* Add a task. Return true if successful, false if
- * the queue's size exceeds limit.
+ * the queue's size exceeds limit or t doesn't contain a callable target.
*/
- inline bool push(const std::function<void(void)> &t) {
- return this->mQueue->push(t);
+ inline bool push(const Task &t) {
+ return (!!t) && this->mQueue->push(t);
}
/*
@@ -56,11 +57,7 @@
this->mQueue->setLimit(limit);
}
private:
-
- // resources managed by the background thread.
- bool *mRunning;
- SynchronizedQueue<std::function<void(void)>> *mQueue;
- std::thread *mThread;
+ std::shared_ptr<SynchronizedQueue<Task>> mQueue;
};
} // namespace details