#pragma region Header //******************************************************************** // created: 2006/12/04 // file path: c:\dev\projects\Sage\Sage\Threading // file: MessageProxy.h // author: Thomas "zeroflag" Kraemer // author email: zeroflag@zeroflag.de // // Copyright (C) 2006 Thomas "zeroflag" Kraemer // // license: (LGPL) // // 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; either // version 2.1 of the License, or (at your option) any later version. // // 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 // // http://www.gnu.org/licenses/lgpl.html#TOC1 // //********************************************************************* #pragma endregion #pragma once #pragma region Includes // basic project header files #include "../Basics/Basics.h" // header file for std::queue #include using std::queue; // header for boost::function #include using boost::function; // header for boost::recursive_mutex #include typedef boost::recursive_mutex Mutex; typedef boost::function Message; #include "MessageQueue.h" #pragma endregion namespace Sage { class Module; namespace Threading { typedef boost::function Message; typedef Mutex::scoped_lock Lock; /** * Serves as an unidirectional, double-buffered message queue between 2 modules. * @remark Only one writer and one reader are allowed. */ class SAGE_API MessageProxy : public MessageQueue { public: virtual ~MessageProxy(); /** * Pushes a new message to the WriteQueue. * @return void * @param Message message */ virtual void push(Message message); /** * Reads and removes the first Message from the ReadQueue. * @return Sage::Threading::Message */ virtual shared_ptr pop(); /** * Swap the read- with the write-queue. * @remark This method locks both, read and write operations. It should only be used from the reader's end and only if isMessageWaiting() returns true. */ void swap(); /** * Locks and clears the Read queue. Should only be done from the Read thread (really!). */ void clearReadQueue(); /** * Locks and clears the Write queue. Should only be done from the Write thread. * @return void */ void clearWriteQueue(); /** * Locks and clears both queues. Use with care. */ void clear(); /** * Returns a scoped lock for the read-queue. * @remark You need to store the returned Lock value in order to keep it locked. * @return Sage::Threading::Lock */ Lock getReadLock(); /** * Returns a scoped lock for the write-queue. * @remark You need to store the returned Lock value in order to keep it locked. * @return Sage::Threading::Lock */ Lock getWriteLock(); virtual bool isEmpty(); virtual void update() {} //TODO: move to protected after debugging. MessageProxy(); protected: /** * Whether there is a message waiting on the write queue. * @remark this uses a volatile boolean that is set by push operations. yield writer- and reader-threads before/after operations if you want to make sure that this method returns the current value. * @return bool */ bool isMessageWaiting() const; queue>* mReadQueue; queue>* mWriteQueue; Mutex mReadMutex; Mutex mWriteMutex; volatile bool mMessageWaiting; friend class Sage::Module; }; } }