From 5836af72687bed763b0ddfe63e5584e3b3fed528 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sat, 26 Jul 2014 12:44:51 -0700 Subject: [PATCH] Clean up hsReaderWriterLock --- Sources/Plasma/CoreLib/CMakeLists.txt | 1 - Sources/Plasma/CoreLib/hsThread.cpp | 109 -------------------------- Sources/Plasma/CoreLib/hsThread.h | 80 ++++++++----------- 3 files changed, 31 insertions(+), 159 deletions(-) delete mode 100644 Sources/Plasma/CoreLib/hsThread.cpp diff --git a/Sources/Plasma/CoreLib/CMakeLists.txt b/Sources/Plasma/CoreLib/CMakeLists.txt index 24385ab8..8de8b9e2 100644 --- a/Sources/Plasma/CoreLib/CMakeLists.txt +++ b/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 diff --git a/Sources/Plasma/CoreLib/hsThread.cpp b/Sources/Plasma/CoreLib/hsThread.cpp deleted file mode 100644 index d36f8bb5..00000000 --- a/Sources/Plasma/CoreLib/hsThread.cpp +++ /dev/null @@ -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 . - -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 lock_count(fReaderCountLock); - std::lock_guard lock(fReaderLock); - fReaderCount++; - if (fReaderCount == 1) - fWriterSema.Wait(); - } - if ( fCallback ) - fCallback->OnLockedForRead( this ); -} - -void hsReaderWriterLock::UnlockForReading() -{ - if ( fCallback ) - fCallback->OnUnlockingForRead(this); - { - std::lock_guard 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 diff --git a/Sources/Plasma/CoreLib/hsThread.h b/Sources/Plasma/CoreLib/hsThread.h index 0da3171c..08a5c388 100644 --- a/Sources/Plasma/CoreLib/hsThread.h +++ b/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 #include #include @@ -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 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 fReaderCount; + std::mutex fReaderLock; + hsSemaphore fWriterSem; }; #endif