wg_message_server.cpp

00001 // wg_message_server.cpp
00002 //
00003 // CMessageServer class implementation
00004 //
00005 //
00006 // Copyright (c) 2002-2004 Rob Wiskow
00007 // rob-dev@boxedchaos.com
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00022 //
00023 
00024 
00025 #include "wgui_include_config.h"
00026 #include "wg_message_server.h"
00027 #include "wg_application.h"
00028 #include "std_ex.h"
00029 #include "wg_message_client.h"
00030 #include "wg_error.h"
00031 #include "wutil_debug.h"
00032 #include <sstream>
00033 #include <algorithm>
00034 #include <functional>
00035 
00036 
00037 namespace wGui
00038 {
00039 
00040 CMessageServer* CMessageServer::m_pInstance = 0;
00041 
00042 
00043 CMessageServer::CMessageServer(void) : m_bIgnoreAllNewMessages(true)
00044 {
00045      m_pSemaphore = SDL_CreateSemaphore(0);
00046 }
00047 
00048 
00049 CMessageServer::~CMessageServer(void)
00050 {
00051 
00052 }
00053 
00054 
00055 CMessageServer& CMessageServer::Instance(void)
00056 {
00057      if (!m_pInstance)
00058      {
00059           m_pInstance = new CMessageServer;
00060           if (!m_pInstance)
00061           {
00062                throw(Wg_Ex_App(L"CMessageServer::Instance : Unable to instantiate Message Server!"));
00063           }
00064      }
00065 
00066      return *m_pInstance;
00067 }
00068 
00069 
00070 void CMessageServer::RegisterMessageClient(CMessageClient* pClient, CMessage::EMessageType eMessageType, unsigned char Priority)
00071 {
00072      if (!pClient)
00073      {
00074           CApplication::Instance()->GetApplicationLog().AddLogEntry(
00075                L"CMessageServer::RegisterMessageClient : Attempting to register a non-existent message client.", APP_LOG_ERROR);
00076      }
00077      else
00078      {
00079           m_MessageClients[eMessageType].insert(std::make_pair(Priority, s_MessageClientActive(pClient, false)));
00080      }
00081 }
00082 
00083 
00084 void CMessageServer::DeregisterMessageClient(CMessageClient* pClient, CMessage::EMessageType eMessageType)
00085 {
00086      t_MessageClientPriorityMap& PriorityMap = m_MessageClients[eMessageType];
00087      t_MessageClientPriorityMap::iterator iter = PriorityMap.begin();
00088      while (iter != PriorityMap.end())
00089      {
00090           if (iter->second.pClient == pClient)
00091           {
00092                PriorityMap.erase(iter);
00093                iter = PriorityMap.begin();
00094           }
00095           else
00096           {
00097                ++iter;
00098           }
00099      }
00100 }
00101 
00102 
00103 void CMessageServer::DeregisterMessageClient(CMessageClient* pClient)
00104 {
00105      for (t_MessageClientMap::iterator iter = m_MessageClients.begin(); iter != m_MessageClients.end(); ++iter)
00106      {
00107           t_MessageClientPriorityMap::iterator iter2 = iter->second.begin();
00108           while (iter2 != iter->second.end())
00109           {
00110                if (iter2->second.pClient == pClient)
00111                {
00112                     iter->second.erase(iter2);
00113                     iter2 = iter->second.begin();
00114                }
00115                else
00116                {
00117                     ++iter2;
00118                }
00119           }
00120      }
00121 }
00122 
00123 
00124 void CMessageServer::DeliverMessage(void)
00125 {
00126      if (m_MessageQueue.size() > 0)
00127      {
00128           CMessage* pMessage = m_MessageQueue.front();
00129           t_MessageClientPriorityMap& PriorityMap = m_MessageClients[pMessage->MessageType()];
00130 
00131           // we have to make sure that each client only gets the message once,
00132           // even if the handling of one of these messages changes the message map
00133           for (t_MessageClientPriorityMap::iterator iter = PriorityMap.begin(); iter != PriorityMap.end(); ++iter)
00134           {
00135                iter->second.bWaitingForMessage = true;
00136           }
00137 
00138           bool bFinished = false;
00139           while (! bFinished)
00140           {
00141                t_MessageClientPriorityMap::iterator iter = PriorityMap.begin();
00142                for (; iter != PriorityMap.end(); ++iter)
00143                {
00144                     if (iter->second.bWaitingForMessage)
00145                     {
00146                          iter->second.bWaitingForMessage = false;
00147                          bFinished = iter->second.pClient->HandleMessage(pMessage);
00148                          break;
00149                     }
00150                }
00151                if (iter == PriorityMap.end())
00152                {
00153                     bFinished = true;
00154                }
00155           }
00156 
00157           m_MessageQueue.pop_front();
00158           delete pMessage;
00159      }
00160 }
00161 
00162 
00164 
00165 struct Duplicate_APP_PAINT : public std::unary_function<CMessage*, bool>
00166 {
00167 public:
00170      Duplicate_APP_PAINT(const CMessageClient* pClient) : m_pClient(pClient) { }
00174      bool operator() (CMessage* pMessage) const
00175      {
00176           bool bResult = (pMessage->MessageType() == CMessage::APP_PAINT) && (pMessage->Destination() == m_pClient);
00177           return bResult;
00178      }
00179 
00180 private:
00182      const CMessageClient* m_pClient;
00183 };
00184 
00185 
00186 void CMessageServer::QueueMessage(CMessage* pMessage)
00187 {
00188      if (!m_bIgnoreAllNewMessages)
00189      {
00190           // check for and remove any redundant APP_PAINT messages in the queue
00191           if (pMessage->MessageType() == CMessage::APP_PAINT)
00192           {
00193                m_MessageQueue.erase(std::remove_if(m_MessageQueue.begin(), m_MessageQueue.end(), Duplicate_APP_PAINT(pMessage->Destination())), m_MessageQueue.end());
00194           }
00195 
00196           m_MessageQueue.push_back(pMessage);
00197      }
00198 }
00199 
00200 }

Generated on Wed May 16 23:11:26 2007 for wGui by  doxygen 1.5.1