You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
3.1 KiB
95 lines
3.1 KiB
/*
|
|
* 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}, mAcquired(false) {}
|
|
|
|
// Unlocks manager-owned mutex
|
|
AutoConditionLock::~AutoConditionLock() {
|
|
// Unset the condition and wake everyone up before releasing lock
|
|
if (mAcquired) {
|
|
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;
|
|
scopedLock->mAcquired = 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;
|
|
scopedLock->mAcquired = true;
|
|
return scopedLock;
|
|
}
|
|
|
|
}; // namespace android
|