phoenix-firestorm/indra/llcommon/llmutex.cpp

228 lines
4.0 KiB
C++

/**
* @file llmutex.cpp
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llmutex.h"
#include "llthread.h"
#include "lltimer.h"
//============================================================================
LLMutex::LLMutex() :
mCount(0)
{
}
LLMutex::~LLMutex()
{
}
void LLMutex::lock()
{
if(isSelfLocked())
{ //redundant lock
mCount++;
return;
}
mMutex.lock();
#if MUTEX_DEBUG
// Have to have the lock before we can access the debug info
auto id = LLThread::currentID();
if (mIsLocked[id] != FALSE)
LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL;
mIsLocked[id] = TRUE;
#endif
mLockingThread = LLThread::currentID();
}
void LLMutex::unlock()
{
if (mCount > 0)
{ //not the root unlock
mCount--;
return;
}
#if MUTEX_DEBUG
// Access the debug info while we have the lock
auto id = LLThread::currentID();
if (mIsLocked[id] != TRUE)
LL_ERRS() << "Not locked in Thread: " << id << LL_ENDL;
mIsLocked[id] = FALSE;
#endif
mLockingThread = LLThread::id_t();
mMutex.unlock();
}
bool LLMutex::isLocked()
{
if (!mMutex.try_lock())
{
return true;
}
else
{
mMutex.unlock();
return false;
}
}
bool LLMutex::isSelfLocked()
{
return mLockingThread == LLThread::currentID();
}
LLThread::id_t LLMutex::lockingThread() const
{
return mLockingThread;
}
bool LLMutex::trylock()
{
if(isSelfLocked())
{ //redundant lock
mCount++;
return true;
}
if (!mMutex.try_lock())
{
return false;
}
#if MUTEX_DEBUG
// Have to have the lock before we can access the debug info
auto id = LLThread::currentID();
if (mIsLocked[id] != FALSE)
LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL;
mIsLocked[id] = TRUE;
#endif
mLockingThread = LLThread::currentID();
return true;
}
//============================================================================
LLCondition::LLCondition() :
LLMutex()
{
}
LLCondition::~LLCondition()
{
}
void LLCondition::wait()
{
std::unique_lock< std::mutex > lock(mMutex);
mCond.wait(lock);
}
void LLCondition::signal()
{
mCond.notify_one();
}
void LLCondition::broadcast()
{
mCond.notify_all();
}
LLMutexTrylock::LLMutexTrylock(LLMutex* mutex)
: mMutex(mutex),
mLocked(false)
{
if (mMutex)
mLocked = mMutex->trylock();
}
LLMutexTrylock::LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms)
: mMutex(mutex),
mLocked(false)
{
if (!mMutex)
return;
for (U32 i = 0; i < aTries; ++i)
{
mLocked = mMutex->trylock();
if (mLocked)
break;
ms_sleep(delay_ms);
}
}
LLMutexTrylock::~LLMutexTrylock()
{
if (mMutex && mLocked)
mMutex->unlock();
}
//---------------------------------------------------------------------
//
// LLScopedLock
//
LLScopedLock::LLScopedLock(std::mutex* mutex) : mMutex(mutex)
{
if(mutex)
{
mutex->lock();
mLocked = true;
}
else
{
mLocked = false;
}
}
LLScopedLock::~LLScopedLock()
{
unlock();
}
void LLScopedLock::unlock()
{
if(mLocked)
{
mMutex->unlock();
mLocked = false;
}
}
//============================================================================