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#include "AutoConditionLock.h" 18cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 19cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunknamespace android { 20cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 21cc776718c0be7c31fe5ab4fc1446d377be60369fRuben BrunkWaitableMutexWrapper::WaitableMutexWrapper(Mutex* mutex) : mMutex{mutex}, mState{false} {} 22cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 23cc776718c0be7c31fe5ab4fc1446d377be60369fRuben BrunkWaitableMutexWrapper::~WaitableMutexWrapper() {} 24cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 25cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk// Locks manager-owned mutex 26cc776718c0be7c31fe5ab4fc1446d377be60369fRuben BrunkAutoConditionLock::AutoConditionLock(const std::shared_ptr<WaitableMutexWrapper>& manager) : 2734713c04b5e1a897b0fd905a89622059a787f7a7Shuzhen Wang mManager{manager}, mAutoLock{manager->mMutex}, mAcquired(false) {} 28cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 29cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk// Unlocks manager-owned mutex 30cc776718c0be7c31fe5ab4fc1446d377be60369fRuben BrunkAutoConditionLock::~AutoConditionLock() { 31cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk // Unset the condition and wake everyone up before releasing lock 3234713c04b5e1a897b0fd905a89622059a787f7a7Shuzhen Wang if (mAcquired) { 3334713c04b5e1a897b0fd905a89622059a787f7a7Shuzhen Wang mManager->mState = false; 3434713c04b5e1a897b0fd905a89622059a787f7a7Shuzhen Wang mManager->mCondition.broadcast(); 3534713c04b5e1a897b0fd905a89622059a787f7a7Shuzhen Wang } 36cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk} 37cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 38cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunkstd::unique_ptr<AutoConditionLock> AutoConditionLock::waitAndAcquire( 39cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk const std::shared_ptr<WaitableMutexWrapper>& manager, nsecs_t waitTime) { 40cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 41cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk if (manager == nullptr || manager->mMutex == nullptr) { 42cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk // Bad input, return null 43cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk return std::unique_ptr<AutoConditionLock>{nullptr}; 44cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk } 45cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 46cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk // Acquire scoped lock 47cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk std::unique_ptr<AutoConditionLock> scopedLock(new AutoConditionLock(manager)); 48cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 49cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk // Figure out what time in the future we should hit the timeout 50cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk nsecs_t failTime = systemTime(SYSTEM_TIME_MONOTONIC) + waitTime; 51cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 52cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk // Wait until we timeout, or success 53cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk while(manager->mState) { 54cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk status_t ret = manager->mCondition.waitRelative(*(manager->mMutex), waitTime); 55cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk if (ret != NO_ERROR) { 56cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk // Timed out or whatever, return null 57cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk return std::unique_ptr<AutoConditionLock>{nullptr}; 58cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk } 59cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk waitTime = failTime - systemTime(SYSTEM_TIME_MONOTONIC); 60cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk } 61cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 62cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk // Set the condition and return 63cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk manager->mState = true; 6434713c04b5e1a897b0fd905a89622059a787f7a7Shuzhen Wang scopedLock->mAcquired = true; 65cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk return scopedLock; 66cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk} 67cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 68cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunkstd::unique_ptr<AutoConditionLock> AutoConditionLock::waitAndAcquire( 69cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk const std::shared_ptr<WaitableMutexWrapper>& manager) { 70cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 71cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk if (manager == nullptr || manager->mMutex == nullptr) { 72cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk // Bad input, return null 73cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk return std::unique_ptr<AutoConditionLock>{nullptr}; 74cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk } 75cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 76cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk // Acquire scoped lock 77cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk std::unique_ptr<AutoConditionLock> scopedLock(new AutoConditionLock(manager)); 78cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 79cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk // Wait until we timeout, or success 80cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk while(manager->mState) { 81cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk status_t ret = manager->mCondition.wait(*(manager->mMutex)); 82cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk if (ret != NO_ERROR) { 83cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk // Timed out or whatever, return null 84cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk return std::unique_ptr<AutoConditionLock>{nullptr}; 85cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk } 86cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk } 87cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 88cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk // Set the condition and return 89cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk manager->mState = true; 9034713c04b5e1a897b0fd905a89622059a787f7a7Shuzhen Wang scopedLock->mAcquired = true; 91cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk return scopedLock; 92cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk} 93cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 94cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk}; // namespace android 95