aboutsummaryrefslogtreecommitdiff
path: root/utils/Worker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/Worker.cpp')
-rw-r--r--utils/Worker.cpp94
1 files changed, 94 insertions, 0 deletions
diff --git a/utils/Worker.cpp b/utils/Worker.cpp
new file mode 100644
index 0000000..1f30588
--- /dev/null
+++ b/utils/Worker.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015-2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Worker.h"
+
+#include <sys/prctl.h>
+#include <sys/resource.h>
+
+namespace android {
+
+Worker::Worker(const char *name, int priority)
+ : name_(name), priority_(priority), exit_(false), initialized_(false) {
+}
+
+Worker::~Worker() {
+ Exit();
+}
+
+int Worker::InitWorker() {
+ std::lock_guard<std::mutex> lk(mutex_);
+ if (initialized())
+ return -EALREADY;
+
+ thread_ = std::unique_ptr<std::thread>(
+ new std::thread(&Worker::InternalRoutine, this));
+ initialized_ = true;
+ exit_ = false;
+
+ return 0;
+}
+
+void Worker::Exit() {
+ std::unique_lock<std::mutex> lk(mutex_);
+ exit_ = true;
+ if (initialized()) {
+ lk.unlock();
+ cond_.notify_all();
+ thread_->join();
+ initialized_ = false;
+ }
+}
+
+int Worker::WaitForSignalOrExitLocked(int64_t max_nanoseconds) {
+ int ret = 0;
+ if (should_exit())
+ return -EINTR;
+
+ std::unique_lock<std::mutex> lk(mutex_, std::adopt_lock);
+ if (max_nanoseconds < 0) {
+ cond_.wait(lk);
+ } else if (std::cv_status::timeout ==
+ cond_.wait_for(lk, std::chrono::nanoseconds(max_nanoseconds))) {
+ ret = -ETIMEDOUT;
+ }
+
+ // exit takes precedence on timeout
+ if (should_exit())
+ ret = -EINTR;
+
+ // release leaves mutex locked when going out of scope
+ lk.release();
+
+ return ret;
+}
+
+void Worker::InternalRoutine() {
+ setpriority(PRIO_PROCESS, 0, priority_);
+ prctl(PR_SET_NAME, name_.c_str());
+
+ std::unique_lock<std::mutex> lk(mutex_, std::defer_lock);
+
+ while (true) {
+ lk.lock();
+ if (should_exit())
+ return;
+ lk.unlock();
+
+ Routine();
+ }
+}
+} // namespace android