// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero 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 Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef NL_READER_WRITER_H #define NL_READER_WRITER_H #include "types_nl.h" #include "mutex.h" namespace NLMISC { /** * This class allows a reader/writer ressource usage policy. * \author Benjamin Legros * \author Nevrax France * \date 2001 */ class CReaderWriter { private: volatile CMutex _Fairness; volatile CMutex _ReadersMutex; volatile CMutex _RWMutex; volatile sint _ReadersLevel; public: CReaderWriter(); ~CReaderWriter(); void enterReader() { const_cast(_Fairness).enter(); const_cast(_ReadersMutex).enter(); ++_ReadersLevel; if (_ReadersLevel == 1) const_cast(_RWMutex).enter(); const_cast(_ReadersMutex).leave(); const_cast(_Fairness).leave(); } void leaveReader() { const_cast(_ReadersMutex).enter(); --_ReadersLevel; if (_ReadersLevel == 0) const_cast(_RWMutex).leave(); const_cast(_ReadersMutex).leave(); } void enterWriter() { const_cast(_Fairness).enter(); const_cast(_RWMutex).enter(); const_cast(_Fairness).leave(); } void leaveWriter() { const_cast(_RWMutex).leave(); } }; /** * This class uses a CReaderWriter object to implement a synchronized object (see mutex.h for standard CSynchronized.) * \author Benjamin Legros * \author Nevrax France * \date 2001 */ template class CRWSynchronized { public: class CReadAccessor { CRWSynchronized *_RWSynchronized; public: CReadAccessor(CRWSynchronized *cs) { _RWSynchronized = cs; const_cast(_RWSynchronized->_RWSync).enterReader(); } ~CReadAccessor() { const_cast(_RWSynchronized->_RWSync).leaveReader(); } const T &value() { return const_cast(_RWSynchronized->_Value); } }; class CWriteAccessor { CRWSynchronized *_RWSynchronized; public: CWriteAccessor(CRWSynchronized *cs) { _RWSynchronized = cs; const_cast(_RWSynchronized->_RWSync).enterWriter(); } ~CWriteAccessor() { const_cast(_RWSynchronized->_RWSync).leaveWriter(); } T &value() { return const_cast(_RWSynchronized->_Value); } }; private: friend class CRWSynchronized::CReadAccessor; friend class CRWSynchronized::CWriteAccessor; volatile CReaderWriter _RWSync; volatile T _Value; }; } // NLMISC #endif // NL_READER_WRITER_H /* End of reader_writer.h */