MercuryMessages.cpp

Go to the documentation of this file.
00001 #include "global.h"
00002 #include "MercuryMessages.h"
00003 #include "MercuryThreads.h"
00004 #include "MercuryUtil.h"
00005 #include "MercuryLog.h"
00006 
00007 using namespace std;
00008 
00009 MercuryMessageManager   *MESSAGEMAN = NULL;
00010 
00011 extern volatile float DTIME;
00012 
00013 void* AutoUpdateMessages( void * data )
00014 {
00015     while ( true )
00016     {
00017         Sleep(10);
00018         ((MercuryMessageManager*)data)->Update(DTIME);
00019     }
00020     return 0;
00021 }
00022 
00023 MercuryMessageManager::MercuryMessageManager()
00024     :m_fTotalTime( 0 )
00025 { 
00026     //no code
00027 }
00028 
00029 void MercuryMessageManager::BroadcastMessage( const MString &name, const PStack& data )
00030 {
00031     MercuryCallback* cb = NULL;
00032     map < MString, MVector< MercuryCallback > >::iterator mpi;
00033     MLockPtr<std::map < MString, MVector< MercuryCallback > > > callbacks(m_mCallbacks, m_mutexCallback);
00034 
00035     mpi = callbacks->find(name);
00036 
00037     if ( mpi == callbacks->end() )
00038         return;
00039 
00040     //make a copy of the vector incase the fector changes
00041     //during processes (it can becuse of unregister)
00042 //  MVector< MercuryCallback > clbk = mpi->second;
00043 
00044     //XXX FIX ME - very crappy fix
00045     for ( unsigned int i = 0; i < mpi->second.size() ;)
00046     {
00047         unsigned int t = mpi->second.size();
00048         PStack argscopy = data;
00049         cb = &(mpi->second[i]); 
00050         cb->funct( name, cb->luser, argscopy);
00051         if(mpi->second.size() >= t)
00052             i++;
00053     }
00054 }
00055 
00056 void MercuryMessageManager::Subscribe( const MString &name, MercuryCallback cb )
00057 {
00058     MLockPtr<std::map < MString, MVector< MercuryCallback > > >(m_mCallbacks, m_mutexCallback)->operator[](name).push_back(cb);
00059 }
00060 
00061 void MercuryMessageManager::Unsubscribe(  const MString &name, MercuryCallback cb )
00062 {
00063     map < MString, MVector< MercuryCallback > >::iterator mpi;
00064     MLockPtr<std::map < MString, MVector< MercuryCallback > > > callbacks(m_mCallbacks, m_mutexCallback);
00065     mpi = callbacks->find( name );
00066 
00067     if ( mpi == callbacks->end() )
00068         return;
00069 
00070     for( unsigned int i = 0; i < mpi->second.size(); i++ )
00071         if( mpi->second[i] == cb )
00072             mpi->second.remove( i );
00073 }
00074 
00075 void MercuryMessageManager::PostSystemMessage( const MString &name, const PStack& data, float fTimeInFuture )
00076 {
00077     MLockPtr<MHeap< PostData > > postCodes(m_mPostCodes, m_mutexPost);
00078     (*postCodes).push( PostData(fTimeInFuture + m_fTotalTime, name, data) );
00079 }
00080 
00081 void MercuryMessageManager::Update( float fDeltaTime ) 
00082 {
00083     std::map < float, unsigned int >::iterator iterPC;
00084 
00085     MLockPtr<MHeap< PostData > > postCodes(m_mPostCodes, m_mutexPost);
00086 
00087     m_fTotalTime += fDeltaTime;
00088 
00089     while(!postCodes->empty())
00090     {
00091         const PostData& pd = postCodes->head();
00092         if(pd.time <= m_fTotalTime)
00093         {
00094             BroadcastMessage( pd.name, pd.data );
00095             postCodes->pop();
00096         }
00097         else
00098             return;
00099     }
00100 }
00101 
00102 MercuryMessageSubscription::MercuryMessageSubscription()
00103 {
00104     if ( !MESSAGEMAN )
00105         MESSAGEMAN = new MercuryMessageManager;
00106 }
00107 
00108 MercuryMessageSubscription::MercuryMessageSubscription( const MString &name, MercuryCallback cb )
00109 {
00110     MercuryMessageSubscription::MercuryMessageSubscription();
00111     Subscribe( name, cb );
00112 }
00113 
00114 
00115 MercuryMessageSubscription::~MercuryMessageSubscription()
00116 {
00117     Unsubscribe( );
00118 }
00119 
00120 void MercuryMessageSubscription::Unsubscribe( )
00121 {
00122     if ( m_pCallback != NULL && MESSAGEMAN )
00123     {
00124         MESSAGEMAN->Unsubscribe( m_sName, m_pCallback );
00125         m_pCallback.funct = NULL;
00126         m_pCallback.luser = NULL;
00127         m_sName = "";
00128     }
00129 }
00130 
00131 void MercuryMessageSubscription::Subscribe( const MString &name, MercuryCallback cb )
00132 {
00133     Unsubscribe( );
00134     m_sName = name;
00135     m_pCallback = cb;
00136     MESSAGEMAN->Subscribe( name, cb );
00137 }
00138 
00139 MercuryMessageObjectSubscription::MercuryMessageObjectSubscription( const MString &sName, MercuryMessageObjectData data, MercuryCallbackFunction handler )
00140 {
00141     m_pData = data;
00142     m_pCallback.luser = &m_pData;
00143     m_pCallback.funct = handler;
00144     m_sName = sName;
00145     MESSAGEMAN->Subscribe( sName, m_pCallback );
00146 }
00147 
00148 MercuryMessageObjectSubscription::~MercuryMessageObjectSubscription()
00149 {
00150     MESSAGEMAN->Unsubscribe( m_sName, m_pCallback );
00151 }
00152 
00153 void MercuryMessageHandler::ProcessMessage( const MString & name, void * mudata, PStack & data )
00154 {
00155     MercuryMessageObjectData * k = (MercuryMessageObjectData*)mudata;
00156     k->m_qHandler->Message( k->m_iNumber, data, name );
00157 }
00158 
00159 void MercuryMessageHandler::RegisterMessage( int messageID, const MString & name )
00160 {
00161     MercuryMessageObjectData k;
00162     k.m_iNumber = messageID;
00163     k.m_qHandler = this;
00164     MercuryMessageObjectSubscription * newsub = new MercuryMessageObjectSubscription( name, k , ProcessMessage );
00165     m_lCallbacks.push_back( newsub );
00166 }
00167 
00168 void MercuryMessageHandler::UnregisterMessage( int messageID, const MString & name )
00169 {
00170     MDequeIterator< MAutoPtr<MercuryMessageObjectSubscription> > i = m_lCallbacks.begin();
00171     for (i = m_lCallbacks.begin(); i != m_lCallbacks.end(); ++i)
00172         if ((*(*i)).TestOwner(name, this))
00173         {
00174             m_lCallbacks.erase(i);
00175             return;
00176         }
00177 }
00178 
00179 void HGEXPORT BroadcastPreExisting( const char * sMessageName, int iMPStack )
00180 {
00181     PStack * s = GetMPStack( iMPStack );
00182     if ( s )
00183         MESSAGEMAN->BroadcastMessage( MString( sMessageName ), *s );
00184 }
00185 
00186 /* 
00187  * Copyright (c) 2005-2006 Charles Lohr, Joshua Allen
00188  * All rights reserved.
00189  *
00190  * Redistribution and use in source and binary forms, with or
00191  * without modification, are permitted provided that the following
00192  * conditions are met:
00193  *  -   Redistributions of source code must retain the above
00194  *      copyright notice, this list of conditions and the following disclaimer.
00195  *  -   Redistributions in binary form must reproduce the above copyright
00196  *      notice, this list of conditions and the following disclaimer in
00197  *      the documentation and/or other materials provided with the distribution.
00198  *  -   Neither the name of the Mercury Engine nor the names of its
00199  *      contributors may be used to endorse or promote products derived from
00200  *      this software without specific prior written permission.
00201  *
00202  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00203  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00204  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00205  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00206  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00207  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00208  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00209  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00210  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00211  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00212  */

Hosted by SourceForge.net Logo