blob: f98282c23255cf8b9e8656e99391fac70f5d7614 [file]
/**
* Copyright (C) 2013 kangliqiang ,kangliq@163.com
*
* 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 "Mutex.h"
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>
namespace kpr
{
Mutex::Mutex()
{
::pthread_mutex_init(&m_mutex, NULL);
}
Mutex::~Mutex()
{
::pthread_mutex_destroy(&m_mutex);
}
void Mutex::Lock() const
{
::pthread_mutex_lock(&m_mutex);
}
bool Mutex::TryLock() const
{
int ret = ::pthread_mutex_trylock(&m_mutex);
return (ret == 0);
}
bool Mutex::TryLock(int timeout) const
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += (timeout/1000);
ts.tv_nsec += (timeout%1000) * 1000 * 1000;
int ret = ::pthread_mutex_timedlock(&m_mutex, &ts);
return (ret == 0);
}
void Mutex::Unlock() const
{
::pthread_mutex_unlock(&m_mutex);
}
//***********
//RWMutex
//***************
RWMutex::RWMutex()
{
::pthread_rwlock_init(&m_mutex, NULL);
}
RWMutex::~RWMutex()
{
::pthread_rwlock_destroy(&m_mutex);
}
void RWMutex::ReadLock() const
{
::pthread_rwlock_rdlock(&m_mutex);
}
void RWMutex::WriteLock() const
{
::pthread_rwlock_wrlock(&m_mutex);
}
bool RWMutex::TryReadLock() const
{
int ret = ::pthread_rwlock_tryrdlock(&m_mutex);
return (ret == 0);
}
bool RWMutex::TryReadLock(int timeout) const
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += (timeout/1000);
ts.tv_nsec += (timeout%1000) * 1000 * 1000;
int ret = ::pthread_rwlock_timedrdlock(&m_mutex, &ts);
return (ret == 0);
}
bool RWMutex::TryWriteLock() const
{
int ret = ::pthread_rwlock_trywrlock(&m_mutex);
return (ret == 0);
}
bool RWMutex::TryWriteLock(int timeout) const
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += (timeout/1000);
ts.tv_nsec += (timeout%1000) * 1000 * 1000;
int ret = ::pthread_rwlock_timedwrlock(&m_mutex, &ts);
return (ret == 0);
}
void RWMutex::Unlock() const
{
::pthread_rwlock_unlock(&m_mutex);
}
//***********
//RecursiveMutex
//***************
RecursiveMutex::RecursiveMutex()
: m_count(0),
m_owner(ThreadId())
{
::pthread_mutex_init(&m_mutex, NULL);
}
RecursiveMutex::~RecursiveMutex()
{
::pthread_mutex_destroy(&m_mutex);
}
bool RecursiveMutex::Lock()const
{
return ((RecursiveMutex*)this)->lock(1);
}
bool RecursiveMutex::Unlock()const
{
return ((RecursiveMutex*)this)->unlock();
}
bool RecursiveMutex::TryLock()const
{
return ((RecursiveMutex*)this)->tryLock();
}
ThreadId RecursiveMutex::GetOwner()const
{
m_internal.Lock();
ThreadId id;
if (m_count > 0)
{
id = m_owner;
}
m_internal.Unlock();
return id;
}
bool RecursiveMutex::lock(int count)
{
bool rc = false;
bool obtained = false;
while (!obtained)
{
m_internal.Lock();
if (m_count == 0)
{
m_count = count;
m_owner = ThreadId::GetCurrentThreadId();
obtained = true;
rc = true;
try
{
::pthread_mutex_lock(&m_mutex);
}
catch (...)
{
try
{
m_internal.Unlock();
}
catch (...)
{
}
throw;
}
}
else if (m_owner == ThreadId::GetCurrentThreadId())
{
m_count += count;
obtained = true;
}
m_internal.Unlock();
if (!obtained)
{
::pthread_mutex_lock(&m_mutex);
::pthread_mutex_unlock(&m_mutex);
}
}
return rc;
}
bool RecursiveMutex::tryLock()
{
bool obtained = false;
m_internal.Lock();
if (m_count == 0)
{
m_count = 1;
m_owner = ThreadId::GetCurrentThreadId();
obtained = true;
try
{
::pthread_mutex_lock(&m_mutex);
}
catch (...)
{
try
{
m_internal.Unlock();
}
catch (...)
{
}
throw;
}
}
else if (m_owner == ThreadId::GetCurrentThreadId())
{
++m_count;
obtained = true;
}
m_internal.Unlock();
return obtained;
}
bool RecursiveMutex::unlock()
{
bool rc;
m_internal.Lock();
if (--m_count == 0)
{
m_owner = ThreadId();
::pthread_mutex_unlock(&m_mutex);
rc = true;
}
else
{
rc = false;
}
m_internal.Unlock();
return rc;
}
unsigned int RecursiveMutex::reset4Condvar()
{
m_internal.Lock();
unsigned int count = m_count;
m_count = 0;
m_owner = ThreadId();
m_internal.Unlock();
return count;
}
}