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
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
00041
00042
00043
00044
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
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212