/* * 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 #include 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 lk(mutex_); if (initialized()) return -EALREADY; thread_ = std::unique_ptr( new std::thread(&Worker::InternalRoutine, this)); initialized_ = true; exit_ = false; return 0; } void Worker::Exit() { std::unique_lock 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 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 lk(mutex_, std::defer_lock); while (true) { lk.lock(); if (should_exit()) return; lk.unlock(); Routine(); } } }