dispatcher.cpp

Engine/source/util/messaging/dispatcher.cpp

More...

Classes:

class

Internal class used by the dispatcher.

Namespaces:

namespace

Namespace for the message dispatcher functions.

Public Defines

define
gDispatchData() _dispatcherGetGDispatchData()

Public Functions

DefineEngineFunction(dispatchMessage , bool , (const char *queueName, const char *message, const char *data) , ("") , "(string queueName, string message, string data)" "@brief <a href="/coding/file/windispatch_8h/#windispatch_8h_1a87cb262856b561a9d947228298d12a22">Dispatch</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> message <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n\n</a>" "@param queueName Queue <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> dispatch the message <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to\n</a>" "@param message <a href="/coding/class/classmessage/">Message</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dispatch\n</a>" "@param data Data <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">message\n</a>" "@return True <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> success, false <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">failure\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dispatchMessageObject\n</a>" " @ingroup Messaging" )
DefineEngineFunction(dispatchMessageObject , bool , (const char *queueName, const char *message) , ("", "") , "(string queueName, string message)" "@brief <a href="/coding/file/windispatch_8h/#windispatch_8h_1a87cb262856b561a9d947228298d12a22">Dispatch</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> message object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n\n</a>" "@param queueName Queue <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> dispatch the message <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to\n</a>" "@param message <a href="/coding/class/classmessage/">Message</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dispatch\n</a>" "@return true <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> success, false <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">failure\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dispatchMessage\n</a>" " @ingroup Messaging" )
DefineEngineFunction(isQueueRegistered , bool , (const char *queueName) , "(string queueName)" "@brief Determines <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> dispatcher queue <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">exists\n\n</a>" "@param queueName <a href="/coding/class/classstring/">String</a> containing the name of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n</a>" "@ingroup Messaging" )
DefineEngineFunction(registerMessageListener , bool , (const char *queueName, const char *listenerName) , "(string queueName, string listener)" "@brief Registers an event <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">message\n\n</a>" "@param queueName <a href="/coding/class/classstring/">String</a> containing the name of queue <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> attach listener <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to\n</a>" "@param listener Name of event <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">messenger\n</a>" "@ingroup Messaging" )
DefineEngineFunction(registerMessageQueue , void , (const char *queueName) , "(string queueName)" "@brief Registeres <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> dispatcher <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n\n</a>" "@param queueName <a href="/coding/class/classstring/">String</a> containing the name of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n</a>" "@ingroup Messaging" )
DefineEngineFunction(unregisterMessageListener , void , (const char *queueName, const char *listenerName) , "(string queueName, string listener)" "@brief Unregisters an event <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">message\n\n</a>" "@param queueName <a href="/coding/class/classstring/">String</a> containing the name of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n</a>" "@param listener Name of event <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">messenger\n</a>" "@ingroup Messaging" )
DefineEngineFunction(unregisterMessageQueue , void , (const char *queueName) , "(string queueName)" "@brief Unregisters <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> dispatcher <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n\n</a>" "@param queueName <a href="/coding/class/classstring/">String</a> containing the name of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n</a>" "@ingroup Messaging" )

Detailed Description

Public Defines

gDispatchData() _dispatcherGetGDispatchData()

Public Functions

DefineEngineFunction(dispatchMessage , bool , (const char *queueName, const char *message, const char *data) , ("") , "(string queueName, string message, string data)" "@brief <a href="/coding/file/windispatch_8h/#windispatch_8h_1a87cb262856b561a9d947228298d12a22">Dispatch</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> message <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n\n</a>" "@param queueName Queue <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> dispatch the message <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to\n</a>" "@param message <a href="/coding/class/classmessage/">Message</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dispatch\n</a>" "@param data Data <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">message\n</a>" "@return True <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> success, false <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">failure\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dispatchMessageObject\n</a>" " @ingroup Messaging" )

DefineEngineFunction(dispatchMessageObject , bool , (const char *queueName, const char *message) , ("", "") , "(string queueName, string message)" "@brief <a href="/coding/file/windispatch_8h/#windispatch_8h_1a87cb262856b561a9d947228298d12a22">Dispatch</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> message object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n\n</a>" "@param queueName Queue <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> dispatch the message <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to\n</a>" "@param message <a href="/coding/class/classmessage/">Message</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dispatch\n</a>" "@return true <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> success, false <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">failure\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dispatchMessage\n</a>" " @ingroup Messaging" )

DefineEngineFunction(isQueueRegistered , bool , (const char *queueName) , "(string queueName)" "@brief Determines <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> dispatcher queue <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">exists\n\n</a>" "@param queueName <a href="/coding/class/classstring/">String</a> containing the name of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n</a>" "@ingroup Messaging" )

DefineEngineFunction(registerMessageListener , bool , (const char *queueName, const char *listenerName) , "(string queueName, string listener)" "@brief Registers an event <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">message\n\n</a>" "@param queueName <a href="/coding/class/classstring/">String</a> containing the name of queue <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> attach listener <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to\n</a>" "@param listener Name of event <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">messenger\n</a>" "@ingroup Messaging" )

DefineEngineFunction(registerMessageQueue , void , (const char *queueName) , "(string queueName)" "@brief Registeres <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> dispatcher <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n\n</a>" "@param queueName <a href="/coding/class/classstring/">String</a> containing the name of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n</a>" "@ingroup Messaging" )

DefineEngineFunction(unregisterMessageListener , void , (const char *queueName, const char *listenerName) , "(string queueName, string listener)" "@brief Unregisters an event <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">message\n\n</a>" "@param queueName <a href="/coding/class/classstring/">String</a> containing the name of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n</a>" "@param listener Name of event <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">messenger\n</a>" "@ingroup Messaging" )

DefineEngineFunction(unregisterMessageQueue , void , (const char *queueName) , "(string queueName)" "@brief Unregisters <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> dispatcher <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n\n</a>" "@param queueName <a href="/coding/class/classstring/">String</a> containing the name of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue\n</a>" "@ingroup Messaging" )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "util/messaging/dispatcher.h"
 26
 27#include "platform/threads/mutex.h"
 28#include "core/tSimpleHashTable.h"
 29#include "core/util/safeDelete.h"
 30#include "console/engineAPI.h"
 31
 32namespace Dispatcher
 33{
 34
 35//-----------------------------------------------------------------------------
 36// IMessageListener Methods
 37//-----------------------------------------------------------------------------
 38
 39IMessageListener::~IMessageListener()
 40{
 41   for(S32 i = 0;i < mQueues.size();i++)
 42   {
 43      unregisterMessageListener(mQueues[i], this);
 44   }
 45}
 46
 47void IMessageListener::onAddToQueue(StringTableEntry queue)
 48{
 49   // [tom, 8/20/2006] The dispatcher won't let us get added twice, so no need
 50   // to worry about it here.
 51
 52   mQueues.push_back(queue);
 53}
 54
 55void IMessageListener::onRemoveFromQueue(StringTableEntry queue)
 56{
 57   for(S32 i = 0;i < mQueues.size();i++)
 58   {
 59      if(mQueues[i] == queue)
 60      {
 61         mQueues.erase(i);
 62         return;
 63      }
 64   }
 65}
 66
 67//-----------------------------------------------------------------------------
 68// Global State
 69//-----------------------------------------------------------------------------
 70
 71//-----------------------------------------------------------------------------
 72/// @brief Internal class used by the dispatcher
 73//-----------------------------------------------------------------------------
 74typedef struct _DispatchData
 75{
 76   void *mMutex;
 77   SimpleHashTable<MessageQueue> mQueues;
 78   U32 mLastAnonQueueID;
 79
 80   _DispatchData()
 81   {
 82      mMutex = Mutex::createMutex();
 83      mLastAnonQueueID = 0;
 84   }
 85
 86   ~_DispatchData()
 87   {
 88      if(Mutex::lockMutex( mMutex ) )
 89      {
 90         mQueues.clearTables();
 91
 92         Mutex::unlockMutex( mMutex );
 93      }
 94
 95      Mutex::destroyMutex( mMutex );
 96      //SAFE_DELETE(mMutex);
 97      mMutex = NULL;
 98   }
 99
100   const char *makeAnonQueueName()
101   {
102      char buf[512];
103      dSprintf(buf, sizeof(buf), "AnonQueue.%lu", mLastAnonQueueID++);
104      return StringTable->insert(buf);
105   }
106} _DispatchData;
107
108static _DispatchData& _dispatcherGetGDispatchData()
109{
110   static _DispatchData dispatchData;
111   return dispatchData;
112}
113
114#define gDispatchData _dispatcherGetGDispatchData()
115
116
117//-----------------------------------------------------------------------------
118// Queue Registration
119//-----------------------------------------------------------------------------
120
121bool isQueueRegistered(const char *name)
122{
123   MutexHandle mh;
124   if(mh.lock(gDispatchData.mMutex, true))
125   {
126      return gDispatchData.mQueues.retreive(name) != NULL;
127   }
128
129   return false;
130}
131
132void registerMessageQueue(const char *name)
133{
134   if(isQueueRegistered(name))
135      return;
136
137   if(Mutex::lockMutex( gDispatchData.mMutex, true ))
138   {
139      MessageQueue *queue = new MessageQueue;
140      queue->mQueueName = StringTable->insert(name);
141      gDispatchData.mQueues.insert(queue, name);
142
143      Mutex::unlockMutex( gDispatchData.mMutex );
144   }
145}
146
147extern const char * registerAnonMessageQueue()
148{
149   const char *name = NULL;
150   if(Mutex::lockMutex( gDispatchData.mMutex, true ))
151   {
152      name = gDispatchData.makeAnonQueueName();
153      Mutex::unlockMutex( gDispatchData.mMutex );
154   }
155
156   if(name)
157      registerMessageQueue(name);
158
159   return name;
160}
161
162void unregisterMessageQueue(const char *name)
163{
164   MutexHandle mh;
165   if(mh.lock(gDispatchData.mMutex, true))
166   {
167      MessageQueue *queue = gDispatchData.mQueues.remove(name);
168      if(queue == NULL)
169         return;
170
171      // Tell the listeners about it
172      for(S32 i = 0;i < queue->mListeners.size();i++)
173      {
174         queue->mListeners[i]->onRemoveFromQueue(name);
175      }
176
177      delete queue;
178   }
179}
180
181//-----------------------------------------------------------------------------
182// Message Listener Registration
183//-----------------------------------------------------------------------------
184
185bool registerMessageListener(const char *queue, IMessageListener *listener)
186{
187   if(! isQueueRegistered(queue))
188      registerMessageQueue(queue);
189
190   MutexHandle mh;
191
192   if(! mh.lock(gDispatchData.mMutex, true))
193      return false;
194
195   MessageQueue *q = gDispatchData.mQueues.retreive(queue);
196   if(q == NULL)
197   {
198      Con::errorf("Dispatcher::registerMessageListener - Queue '%s' not found?! It should have been added automatically!", queue);
199      return false;
200   }
201
202   for(VectorPtr<IMessageListener *>::iterator i = q->mListeners.begin();i != q->mListeners.end();i++)
203   {
204      if(*i == listener)
205         return false;
206   }
207
208   q->mListeners.push_front(listener);
209   listener->onAddToQueue(StringTable->insert(queue));
210   return true;
211}
212
213void unregisterMessageListener(const char *queue, IMessageListener *listener)
214{
215   if(! isQueueRegistered(queue))
216      return;
217
218   MutexHandle mh;
219
220   if(! mh.lock(gDispatchData.mMutex, true))
221      return;
222
223   MessageQueue *q = gDispatchData.mQueues.retreive(queue);
224   if(q == NULL)
225      return;
226
227   for(VectorPtr<IMessageListener *>::iterator i = q->mListeners.begin();i != q->mListeners.end();i++)
228   {
229      if(*i == listener)
230      {
231         listener->onRemoveFromQueue(StringTable->insert(queue));
232         q->mListeners.erase(i);
233         return;
234      }
235   }
236}
237
238//-----------------------------------------------------------------------------
239// Dispatcher
240//-----------------------------------------------------------------------------
241
242bool dispatchMessage( const char* queue, const char* msg, const char* data)
243{
244   AssertFatal( queue != NULL, "Dispatcher::dispatchMessage - Got a NULL queue name" );
245   AssertFatal( msg != NULL, "Dispatcher::dispatchMessage - Got a NULL message" );
246
247   MutexHandle mh;
248
249   if(! mh.lock(gDispatchData.mMutex, true))
250      return true;
251
252   MessageQueue *q = gDispatchData.mQueues.retreive(queue);
253   if(q == NULL)
254   {
255      Con::errorf("Dispatcher::dispatchMessage - Attempting to dispatch to unknown queue '%s'", queue);
256      return true;
257   }
258
259   return q->dispatchMessage(msg, data);
260}
261
262
263bool dispatchMessageObject(const char *queue, Message *msg)
264{
265   MutexHandle mh;
266
267   if(msg == NULL)
268      return true;
269
270   msg->addReference();
271
272   if(! mh.lock(gDispatchData.mMutex, true))
273   {
274      msg->freeReference();
275      return true;
276   }
277
278   MessageQueue *q = gDispatchData.mQueues.retreive(queue);
279   if(q == NULL)
280   {
281      Con::errorf("Dispatcher::dispatchMessage - Attempting to dispatch to unknown queue '%s'", queue);
282      msg->freeReference();
283      return true;
284   }
285
286   // [tom, 8/19/2006] Make sure that the message is registered with the sim, since
287   // when it's ref count is zero it'll be deleted with deleteObject()
288   if(! msg->isProperlyAdded())
289   {
290      SimObjectId id = Message::getNextMessageID();
291      if(id != 0xffffffff)
292         msg->registerObject(id);
293      else
294      {
295         Con::errorf("dispatchMessageObject: Message was not registered and no more object IDs are available for messages");
296
297         msg->freeReference();
298         return false;
299      }
300   }
301
302   bool bResult = q->dispatchMessageObject(msg);
303   msg->freeReference();
304
305   return bResult;
306}
307
308//-----------------------------------------------------------------------------
309// Internal Functions
310//-----------------------------------------------------------------------------
311
312MessageQueue * getMessageQueue(const char *name)
313{
314   return gDispatchData.mQueues.retreive(name);
315}
316
317extern bool lockDispatcherMutex()
318{
319   return Mutex::lockMutex(gDispatchData.mMutex);
320}
321
322extern void unlockDispatcherMutex()
323{
324   Mutex::unlockMutex(gDispatchData.mMutex);
325}
326
327} // end namespace Dispatcher
328
329//-----------------------------------------------------------------------------
330// Console Methods
331//-----------------------------------------------------------------------------
332
333using namespace Dispatcher;
334
335DefineEngineFunction( isQueueRegistered, bool, (const char * queueName), , "(string queueName)"
336            "@brief Determines if a dispatcher queue exists\n\n"
337            "@param queueName String containing the name of queue\n"
338            "@ingroup Messaging")
339{
340   return Dispatcher::isQueueRegistered(queueName);
341}
342
343DefineEngineFunction( registerMessageQueue, void, (const char *queueName), , "(string queueName)"
344            "@brief Registeres a dispatcher queue\n\n"
345            "@param queueName String containing the name of queue\n"
346            "@ingroup Messaging")
347{
348   return Dispatcher::registerMessageQueue(queueName);
349}
350
351DefineEngineFunction( unregisterMessageQueue, void, (const char *queueName), , "(string queueName)"
352            "@brief Unregisters a dispatcher queue\n\n"
353            "@param queueName String containing the name of queue\n"
354            "@ingroup Messaging")
355{
356   return Dispatcher::unregisterMessageQueue(queueName);
357}
358
359//-----------------------------------------------------------------------------
360
361DefineEngineFunction( registerMessageListener, bool, (const char *queueName, const char *listenerName), , "(string queueName, string listener)"
362            "@brief Registers an event message\n\n"
363            "@param queueName String containing the name of queue to attach listener to\n"
364            "@param listener Name of event messenger\n"
365            "@ingroup Messaging")
366{
367   Dispatcher::IMessageListener *listener = dynamic_cast<Dispatcher::IMessageListener *>(Sim::findObject(listenerName));
368   if(listener == NULL)
369   {
370      Con::errorf("registerMessageListener - Unable to find listener object, not an IMessageListener ?!");
371      return false;
372   }
373
374   return Dispatcher::registerMessageListener(queueName, listener);
375}
376
377DefineEngineFunction( unregisterMessageListener, void, (const char *queueName, const char *listenerName), , "(string queueName, string listener)"
378            "@brief Unregisters an event message\n\n"
379            "@param queueName String containing the name of queue\n"
380            "@param listener Name of event messenger\n"
381            "@ingroup Messaging")
382{
383   Dispatcher::IMessageListener *listener = dynamic_cast<Dispatcher::IMessageListener *>(Sim::findObject(listenerName));
384   if(listener == NULL)
385   {
386      Con::errorf("unregisterMessageListener - Unable to find listener object, not an IMessageListener ?!");
387      return;
388   }
389
390   Dispatcher::unregisterMessageListener(queueName, listener);
391}
392
393//-----------------------------------------------------------------------------
394
395DefineEngineFunction( dispatchMessage, bool, (const char *queueName, const char *message, const char *data), (""), "(string queueName, string message, string data)"
396            "@brief Dispatch a message to a queue\n\n"
397            "@param queueName Queue to dispatch the message to\n"
398            "@param message Message to dispatch\n"
399            "@param data Data for message\n"
400            "@return True for success, false for failure\n"
401            "@see dispatchMessageObject\n"
402            "@ingroup Messaging")
403{
404   return Dispatcher::dispatchMessage(queueName, message, data);
405}
406
407DefineEngineFunction( dispatchMessageObject, bool, (const char *queueName, const char *message), ("", ""), "(string queueName, string message)"
408            "@brief Dispatch a message object to a queue\n\n"
409            "@param queueName Queue to dispatch the message to\n"
410            "@param message Message to dispatch\n"
411            "@return true for success, false for failure\n"
412            "@see dispatchMessage\n"
413            "@ingroup Messaging")
414{
415   Message *msg = dynamic_cast<Message *>(Sim::findObject(message));
416   if(msg == NULL)
417   {
418      Con::errorf("dispatchMessageObject - Unable to find message object");
419      return false;
420   }
421
422   return Dispatcher::dispatchMessageObject(queueName, msg);
423}
424