Browse Source

Clean up hsReaderWriterLock

Michael Hansen 10 years ago
parent
commit
5836af7268
  1. 1
      Sources/Plasma/CoreLib/CMakeLists.txt
  2. 109
      Sources/Plasma/CoreLib/hsThread.cpp
  3. 80
      Sources/Plasma/CoreLib/hsThread.h

1
Sources/Plasma/CoreLib/CMakeLists.txt

@ -26,7 +26,6 @@ set(CoreLib_SOURCES
hsStream.cpp
hsStringTokenizer.cpp
hsTemplates.cpp
hsThread.cpp
hsWide.cpp
pcSmallRect.cpp
plFileSystem.cpp

109
Sources/Plasma/CoreLib/hsThread.cpp

@ -1,109 +0,0 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef CoreLib_Thread
#define CoreLib_Thread
#include "hsThread.h"
//////////////////////////////////////////////////////////////////////////////
hsReaderWriterLock::hsReaderWriterLock(Callback * cb)
: fReaderCount( 0 )
, fWriterSema( 1 )
, fCallback( cb )
{
}
void hsReaderWriterLock::LockForReading()
{
if ( fCallback )
fCallback->OnLockingForRead(this);
{
std::lock_guard<std::mutex> lock_count(fReaderCountLock);
std::lock_guard<std::mutex> lock(fReaderLock);
fReaderCount++;
if (fReaderCount == 1)
fWriterSema.Wait();
}
if ( fCallback )
fCallback->OnLockedForRead( this );
}
void hsReaderWriterLock::UnlockForReading()
{
if ( fCallback )
fCallback->OnUnlockingForRead(this);
{
std::lock_guard<std::mutex> lock(fReaderLock);
fReaderCount--;
if (fReaderCount == 0)
fWriterSema.Signal();
}
if ( fCallback )
fCallback->OnUnlockedForRead( this );
}
void hsReaderWriterLock::LockForWriting()
{
if ( fCallback )
fCallback->OnLockingForWrite( this );
fReaderCountLock.lock();
fWriterSema.Wait();
hsAssert( fReaderCount==0, "Locked for writing, but fReaderCount>0" );
if ( fCallback )
fCallback->OnLockedForWrite( this );
}
void hsReaderWriterLock::UnlockForWriting()
{
if ( fCallback )
fCallback->OnUnlockingForWrite( this );
fWriterSema.Signal();
fReaderCountLock.unlock();
if ( fCallback )
fCallback->OnUnlockedForWrite( this );
}
#endif // CoreLib_Thread

80
Sources/Plasma/CoreLib/hsThread.h

@ -43,6 +43,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#define hsThread_Defined
#include "HeadSpin.h"
#include <atomic>
#include <mutex>
#include <condition_variable>
@ -204,65 +205,46 @@ public:
class hsReaderWriterLock
{
public:
struct Callback
{
virtual void OnLockingForRead( hsReaderWriterLock * lock ) {}
virtual void OnLockedForRead( hsReaderWriterLock * lock ) {}
virtual void OnUnlockingForRead( hsReaderWriterLock * lock ) {}
virtual void OnUnlockedForRead( hsReaderWriterLock * lock ) {}
virtual void OnLockingForWrite( hsReaderWriterLock * lock ) {}
virtual void OnLockedForWrite( hsReaderWriterLock * lock ) {}
virtual void OnUnlockingForWrite( hsReaderWriterLock * lock ) {}
virtual void OnUnlockedForWrite( hsReaderWriterLock * lock ) {}
};
hsReaderWriterLock(Callback * cb=nullptr);
void LockForReading();
void UnlockForReading();
void LockForWriting();
void UnlockForWriting();
hsReaderWriterLock() : fReaderCount(0), fWriterSem(1) { }
private:
int fReaderCount;
std::mutex fReaderCountLock;
std::mutex fReaderLock;
hsSemaphore fWriterSema;
Callback * fCallback;
};
class hsLockForReading
{
hsReaderWriterLock * fLock;
public:
hsLockForReading( hsReaderWriterLock & lock ): fLock( &lock )
{
fLock->LockForReading();
}
hsLockForReading( hsReaderWriterLock * lock ): fLock( lock )
{
fLock->LockForReading();
}
~hsLockForReading()
void LockForReading()
{
fLock->UnlockForReading();
// Don't allow us to start reading if there's still an active writer
std::lock_guard<std::mutex> lock(fReaderLock);
fReaderCount++;
if (fReaderCount == 1) {
// Block writers from starting (wait is a misnomer here)
fWriterSem.Wait();
}
}
};
class hsLockForWriting
{
hsReaderWriterLock * fLock;
public:
hsLockForWriting( hsReaderWriterLock & lock ): fLock( &lock )
void UnlockForReading()
{
fLock->LockForWriting();
fReaderCount--;
if (fReaderCount == 0)
fWriterSem.Signal();
}
hsLockForWriting( hsReaderWriterLock * lock ): fLock( lock )
void LockForWriting()
{
fLock->LockForWriting();
// Blocks new readers from starting
fReaderLock.lock();
// Wait until all readers are done
fWriterSem.Wait();
}
~hsLockForWriting()
void UnlockForWriting()
{
fLock->UnlockForWriting();
fWriterSem.Signal();
fReaderLock.unlock();
}
private:
std::atomic<int> fReaderCount;
std::mutex fReaderLock;
hsSemaphore fWriterSem;
};
#endif

Loading…
Cancel
Save