blob: 968359d021deaf69db34762996827eccddbb399c [file] [log] [blame]
/*
* Copyright (C) 2016 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 <gapic/mutex.h>
#include <gapic/assert.h>
#include <pthread.h>
namespace gapic {
Mutex::Mutex() {
auto mutex = new pthread_mutex_t();
GAPID_ASSERT(pthread_mutex_init(mutex, nullptr) == 0);
_ = mutex;
}
Mutex::~Mutex() {
auto mutex = reinterpret_cast<pthread_mutex_t*>(_);
GAPID_ASSERT(pthread_mutex_destroy(mutex) == 0);
delete mutex;
}
void Mutex::lock() {
auto mutex = reinterpret_cast<pthread_mutex_t*>(_);
GAPID_ASSERT(pthread_mutex_lock(mutex) == 0);
}
void Mutex::unlock() {
auto mutex = reinterpret_cast<pthread_mutex_t*>(_);
GAPID_ASSERT(pthread_mutex_unlock(mutex) == 0);
}
CycleMutex::CycleMutex() : count(0) {
auto mutex = new pthread_mutex_t();
// Make a recursive lock, so that we can detect cyclic locking.
pthread_mutexattr_t attr;
GAPID_ASSERT(pthread_mutexattr_init(&attr) == 0);
GAPID_ASSERT(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == 0);
GAPID_ASSERT(pthread_mutex_init(mutex, &attr) == 0);
GAPID_ASSERT(pthread_mutexattr_destroy(&attr) == 0);
_ = mutex;
}
CycleMutex::~CycleMutex() {
auto mutex = reinterpret_cast<pthread_mutex_t*>(_);
GAPID_ASSERT(pthread_mutex_destroy(mutex) == 0);
delete mutex;
_ = nullptr;
}
bool CycleMutex::lock() {
auto mutex = reinterpret_cast<pthread_mutex_t*>(_);
GAPID_ASSERT(pthread_mutex_lock(mutex) == 0);
++count;
// As we have PTHREAD_MUTEX_RECURSIVE we can get the lock more than once,
// but only in the same thread.
if (count > 1) {
--count;
GAPID_ASSERT(pthread_mutex_unlock(mutex) == 0);
// We already have the lock
return false;
}
return true;
}
void CycleMutex::unlock() {
auto mutex = reinterpret_cast<pthread_mutex_t*>(_);
--count;
GAPID_ASSERT(pthread_mutex_unlock(mutex) == 0);
}
} // namespace gapic