1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <broadcastradio-utils/WorkerThread.h> 18 19 namespace android { 20 21 using std::chrono::milliseconds; 22 using std::chrono::steady_clock; 23 using std::function; 24 using std::lock_guard; 25 using std::mutex; 26 using std::priority_queue; 27 using std::this_thread::sleep_for; 28 using std::unique_lock; 29 30 bool operator<(const WorkerThread::Task& lhs, const WorkerThread::Task& rhs) { 31 return lhs.when > rhs.when; 32 } 33 34 WorkerThread::WorkerThread() : mIsTerminating(false), mThread(&WorkerThread::threadLoop, this) {} 35 36 WorkerThread::~WorkerThread() { 37 { 38 lock_guard<mutex> lk(mMut); 39 mIsTerminating = true; 40 mCond.notify_one(); 41 } 42 mThread.join(); 43 } 44 45 void WorkerThread::schedule(function<void()> task, milliseconds delay) { 46 auto when = steady_clock::now() + delay; 47 48 lock_guard<mutex> lk(mMut); 49 mTasks.push(Task({when, task})); 50 mCond.notify_one(); 51 } 52 53 void WorkerThread::cancelAll() { 54 lock_guard<mutex> lk(mMut); 55 priority_queue<Task>().swap(mTasks); // empty queue 56 } 57 58 void WorkerThread::threadLoop() { 59 while (!mIsTerminating) { 60 unique_lock<mutex> lk(mMut); 61 if (mTasks.empty()) { 62 mCond.wait(lk); 63 continue; 64 } 65 66 auto task = mTasks.top(); 67 if (task.when > steady_clock::now()) { 68 mCond.wait_until(lk, task.when); 69 continue; 70 } 71 72 mTasks.pop(); 73 lk.unlock(); // what() might need to schedule another task 74 task.what(); 75 } 76 } 77 78 } // namespace android 79