Merge "Create thread in passthrough objects lazily."
am: 546ebf4c7d
Change-Id: Ib96c4bd2ff6fd55961f219b8f201a2fca29b020f
diff --git a/base/include/hidl/SynchronizedQueue.h b/base/SynchronizedQueue.h
similarity index 88%
rename from base/include/hidl/SynchronizedQueue.h
rename to base/SynchronizedQueue.h
index efb04e0..0ef9e4f 100644
--- a/base/include/hidl/SynchronizedQueue.h
+++ b/base/SynchronizedQueue.h
@@ -45,11 +45,23 @@
*/
size_t size();
+ std::unique_lock<std::mutex> lock() {
+ return std::unique_lock<std::mutex>(mMutex);
+ }
+
+ bool isInitializedLocked() {
+ return mInitialized;
+ }
+ void setInitializedLocked(bool isInitialized) {
+ mInitialized = isInitialized;
+ }
+
private:
std::condition_variable mCondition;
std::mutex mMutex;
std::queue<T> mQueue;
const size_t mQueueLimit;
+ bool mInitialized;
};
template <typename T>
diff --git a/base/TaskRunner.cpp b/base/TaskRunner.cpp
index 782b40b..d4357bf 100644
--- a/base/TaskRunner.cpp
+++ b/base/TaskRunner.cpp
@@ -15,6 +15,9 @@
*/
#include <hidl/TaskRunner.h>
+
+#include "SynchronizedQueue.h"
+
#include <thread>
namespace android {
@@ -26,15 +29,6 @@
void TaskRunner::start(size_t limit) {
mQueue = std::make_shared<SynchronizedQueue<Task>>(limit);
-
- // 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();
- }
- }}.detach();
}
TaskRunner::~TaskRunner() {
@@ -44,7 +38,28 @@
}
bool TaskRunner::push(const Task &t) {
- return (mQueue != nullptr) && (!!t) && this->mQueue->push(t);
+ if (mQueue == nullptr || !t) {
+ return false;
+ }
+
+ {
+ std::unique_lock<std::mutex> lock = mQueue->lock();
+
+ if (!mQueue->isInitializedLocked()) {
+ // 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();
+ }
+ }}.detach();
+
+ mQueue->setInitializedLocked(true);
+ }
+ }
+
+ return this->mQueue->push(t);
}
} // namespace details
diff --git a/base/include/hidl/TaskRunner.h b/base/include/hidl/TaskRunner.h
index 28ea01c..6a79ebf 100644
--- a/base/include/hidl/TaskRunner.h
+++ b/base/include/hidl/TaskRunner.h
@@ -16,7 +16,6 @@
#ifndef ANDROID_HIDL_TASK_RUNNER_H
#define ANDROID_HIDL_TASK_RUNNER_H
-#include "SynchronizedQueue.h"
#include <memory>
#include <thread>
@@ -24,13 +23,17 @@
namespace hardware {
namespace details {
+using Task = std::function<void(void)>;
+
+template <typename T>
+struct SynchronizedQueue;
+
/*
* A background infinite loop that runs the Tasks push()'ed.
* Equivalent to a simple single-threaded Looper.
*/
class TaskRunner {
public:
- using Task = std::function<void(void)>;
/* Create an empty task runner. Nothing will be done until start() is called. */
TaskRunner();
@@ -44,7 +47,9 @@
/*
* Sets the queue limit. Fails the push operation once the limit is reached.
- * Then kicks off the loop.
+ * This function is named start for legacy reasons and to maintain ABI
+ * stability, but the underlying thread running tasks isn't started until
+ * the first task is pushed.
*/
void start(size_t limit);