1cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk/* 2cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * Copyright (C) 2015 The Android Open Source Project 3cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * 4cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 5cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * you may not use this file except in compliance with the License. 6cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * You may obtain a copy of the License at 7cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * 8cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * http://www.apache.org/licenses/LICENSE-2.0 9cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * 10cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * Unless required by applicable law or agreed to in writing, software 11cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 12cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * See the License for the specific language governing permissions and 14cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * limitations under the License. 15cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk */ 16cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 17cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 18cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk#ifndef ANDROID_SERVICE_UTILS_SCOPED_CONDITION_H 19cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk#define ANDROID_SERVICE_UTILS_SCOPED_CONDITION_H 20cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 21cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk#include <utils/Timers.h> 22cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk#include <utils/Condition.h> 23cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk#include <utils/Errors.h> 24cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk#include <utils/Mutex.h> 25cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 26cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk#include <memory> 27cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 28cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunknamespace android { 29cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 30cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk/** 31cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * WaitableMutexWrapper can be used with AutoConditionLock to construct scoped locks for the 32cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * wrapped Mutex with timeouts for lock acquisition. 33cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk */ 34cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunkclass WaitableMutexWrapper { 35cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk friend class AutoConditionLock; 36cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunkpublic: 37cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk /** 38cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * Construct the ConditionManger with the given Mutex. 39cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk */ 408b0b971b1416738f22488a80be726d1ec12552a8Chih-Hung Hsieh explicit WaitableMutexWrapper(Mutex* mutex); 41cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 42cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk virtual ~WaitableMutexWrapper(); 43cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunkprivate: 44cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk Mutex* mMutex; 45cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk bool mState; 46cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk Condition mCondition; 47cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk}; 48cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 49cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk/** 50cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * AutoConditionLock is a scoped lock similar to Mutex::Autolock, but allows timeouts to be 51cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * specified for lock acquisition. 52cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * 53cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * AutoConditionLock is used with a WaitableMutexWrapper to lock/unlock the WaitableMutexWrapper's 54cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * wrapped Mutex, and wait/set/signal the WaitableMutexWrapper's wrapped condition. To use this, 55cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * call AutoConditionLock::waitAndAcquire to get an instance. This will: 56cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * - Lock the given WaitableMutexWrapper's mutex. 57cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * - Wait for the WaitableMutexWrapper's condition to become false, or timeout. 58cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * - Set the WaitableMutexWrapper's condition to true. 59cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * 60cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * When the AutoConditionLock goes out of scope and is destroyed, this will: 61cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * - Set the WaitableMutexWrapper's condition to false. 62cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * - Signal threads waiting on this condition to wakeup. 63cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * - Release WaitableMutexWrapper's mutex. 64cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk */ 65cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunkclass AutoConditionLock final { 66cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunkpublic: 67cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk AutoConditionLock() = delete; 68cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk AutoConditionLock(const AutoConditionLock& other) = delete; 69cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk AutoConditionLock & operator=(const AutoConditionLock&) = delete; 70cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 71cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk ~AutoConditionLock(); 72cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 73cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk /** 74cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * Make a new AutoConditionLock from a given WaitableMutexWrapper, waiting up to waitTime 75cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * nanoseconds to acquire the WaitableMutexWrapper's wrapped lock. 76cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * 77cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * Return an empty unique_ptr if this fails, or a timeout occurs. 78cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk */ 79cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk static std::unique_ptr<AutoConditionLock> waitAndAcquire( 80cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk const std::shared_ptr<WaitableMutexWrapper>& manager, nsecs_t waitTime); 81cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 82cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk /** 83cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * Make a new AutoConditionLock from a given WaitableMutexWrapper, waiting indefinitely to 84cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * acquire the WaitableMutexWrapper's wrapped lock. 85cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * 86cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk * Return an empty unique_ptr if this fails. 87cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk */ 88cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk static std::unique_ptr<AutoConditionLock> waitAndAcquire( 89cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk const std::shared_ptr<WaitableMutexWrapper>& manager); 90cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunkprivate: 918b0b971b1416738f22488a80be726d1ec12552a8Chih-Hung Hsieh explicit AutoConditionLock(const std::shared_ptr<WaitableMutexWrapper>& manager); 92cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 93cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk std::shared_ptr<WaitableMutexWrapper> mManager; 94cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk Mutex::Autolock mAutoLock; 9534713c04b5e1a897b0fd905a89622059a787f7a7Shuzhen Wang bool mAcquired; 96cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk}; 97cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 98cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk}; // namespace android 99cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 100cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk#endif // ANDROID_SERVICE_UTILS_SCOPED_CONDITION_H 101