/* * Copyright (C) 2015 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 "AutoConditionLock.h" namespace android { WaitableMutexWrapper::WaitableMutexWrapper(Mutex* mutex) : mMutex{mutex}, mState{false} {} WaitableMutexWrapper::~WaitableMutexWrapper() {} // Locks manager-owned mutex AutoConditionLock::AutoConditionLock(const std::shared_ptr<WaitableMutexWrapper>& manager) : mManager{manager}, mAutoLock{manager->mMutex} {} // Unlocks manager-owned mutex AutoConditionLock::~AutoConditionLock() { // Unset the condition and wake everyone up before releasing lock mManager->mState = false; mManager->mCondition.broadcast(); } std::unique_ptr<AutoConditionLock> AutoConditionLock::waitAndAcquire( const std::shared_ptr<WaitableMutexWrapper>& manager, nsecs_t waitTime) { if (manager == nullptr || manager->mMutex == nullptr) { // Bad input, return null return std::unique_ptr<AutoConditionLock>{nullptr}; } // Acquire scoped lock std::unique_ptr<AutoConditionLock> scopedLock(new AutoConditionLock(manager)); // Figure out what time in the future we should hit the timeout nsecs_t failTime = systemTime(SYSTEM_TIME_MONOTONIC) + waitTime; // Wait until we timeout, or success while(manager->mState) { status_t ret = manager->mCondition.waitRelative(*(manager->mMutex), waitTime); if (ret != NO_ERROR) { // Timed out or whatever, return null return std::unique_ptr<AutoConditionLock>{nullptr}; } waitTime = failTime - systemTime(SYSTEM_TIME_MONOTONIC); } // Set the condition and return manager->mState = true; return scopedLock; } std::unique_ptr<AutoConditionLock> AutoConditionLock::waitAndAcquire( const std::shared_ptr<WaitableMutexWrapper>& manager) { if (manager == nullptr || manager->mMutex == nullptr) { // Bad input, return null return std::unique_ptr<AutoConditionLock>{nullptr}; } // Acquire scoped lock std::unique_ptr<AutoConditionLock> scopedLock(new AutoConditionLock(manager)); // Wait until we timeout, or success while(manager->mState) { status_t ret = manager->mCondition.wait(*(manager->mMutex)); if (ret != NO_ERROR) { // Timed out or whatever, return null return std::unique_ptr<AutoConditionLock>{nullptr}; } } // Set the condition and return manager->mState = true; return scopedLock; } }; // namespace android