EventManagerImpl.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. //========================================================================
  2. // EventManagerImpl.cpp : implementation side of the event system
  3. //
  4. // Part of the GameCode4 Application
  5. //
  6. // GameCode4 is the sample application that encapsulates much of the source code
  7. // discussed in "Game Coding Complete - 4th Edition" by Mike McShaffry and David
  8. // "Rez" Graham, published by Charles River Media.
  9. // ISBN-10: 1133776574 | ISBN-13: 978-1133776574
  10. //
  11. // If this source code has found it's way to you, and you think it has helped you
  12. // in any way, do the authors a favor and buy a new copy of the book - there are
  13. // detailed explanations in it that compliment this code well. Buy a copy at Amazon.com
  14. // by clicking here:
  15. // http://www.amazon.com/gp/product/1133776574/ref=olp_product_details?ie=UTF8&me=&seller=
  16. //
  17. // There's a companion web site at http://www.mcshaffry.com/GameCode/
  18. //
  19. // The source code is managed and maintained through Google Code:
  20. // http://code.google.com/p/gamecode4/
  21. //
  22. // (c) Copyright 2012 Michael L. McShaffry and David Graham
  23. //
  24. // This program is free software; you can redistribute it and/or
  25. // modify it under the terms of the GNU Lesser GPL v3
  26. // as published by the Free Software Foundation.
  27. //
  28. // This program is distributed in the hope that it will be useful,
  29. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  30. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  31. // http://www.gnu.org/licenses/lgpl-3.0.txt for more details.
  32. //
  33. // You should have received a copy of the GNU Lesser GPL v3
  34. // along with this program; if not, write to the Free Software
  35. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  36. //
  37. //========================================================================
  38. #include "../Unix/GameCodeStd.h"
  39. #include "EventManagerImpl.h"
  40. #include "../Utilities/String.h"
  41. #include <SDL3/SDL.h>
  42. //---------------------------------------------------------------------------------------------------------------------
  43. // EventManager::EventManager
  44. //---------------------------------------------------------------------------------------------------------------------
  45. EventManager::EventManager(const char* pName, bool setAsGlobal)
  46. : IEventManager(pName, setAsGlobal)
  47. {
  48. m_activeQueue = 0;
  49. }
  50. //---------------------------------------------------------------------------------------------------------------------
  51. // EventManager::~EventManager
  52. //---------------------------------------------------------------------------------------------------------------------
  53. EventManager::~EventManager()
  54. {
  55. //
  56. }
  57. //---------------------------------------------------------------------------------------------------------------------
  58. // EventManager::VAddListener
  59. //---------------------------------------------------------------------------------------------------------------------
  60. bool EventManager::VAddListener(const EventListenerDelegate& eventDelegate, const EventType& type)
  61. {
  62. GCC_LOG("Events", "Attempting to add delegate function for event type: " + ToStr(type, 16));
  63. EventListenerList& eventListenerList = m_eventListeners[type]; // this will find or create the entry;
  64. for (auto it = eventListenerList.begin(); it != eventListenerList.end(); ++it)
  65. {
  66. if (eventDelegate == (*it))
  67. {
  68. GCC_WARNING("Attempting to double-register a delegate");
  69. return false;
  70. }
  71. }
  72. eventListenerList.push_back(eventDelegate);
  73. GCC_LOG("Events", "Successfully added delegate for event type: " + ToStr(type, 16));
  74. return true;
  75. }
  76. //---------------------------------------------------------------------------------------------------------------------
  77. // EventManager::VRemoveListener
  78. //---------------------------------------------------------------------------------------------------------------------
  79. bool EventManager::VRemoveListener(const EventListenerDelegate& eventDelegate, const EventType& type)
  80. {
  81. GCC_LOG("Events", "Attempting to remove delegate function from event type: " + ToStr(type, 16));
  82. bool success = false;
  83. auto findIt = m_eventListeners.find(type);
  84. if (findIt != m_eventListeners.end())
  85. {
  86. EventListenerList& listeners = findIt->second;
  87. for (auto it = listeners.begin(); it != listeners.end(); ++it)
  88. {
  89. if (eventDelegate == (*it))
  90. {
  91. listeners.erase(it);
  92. GCC_LOG("Events", "Successfully removed delegate function from event type: " + ToStr(type, 16));
  93. success = true;
  94. break; // we don't need to continue because it should be impossible for the same delegate function to be registered for the same event more than once
  95. }
  96. }
  97. }
  98. return success;
  99. }
  100. //---------------------------------------------------------------------------------------------------------------------
  101. // EventManager::VTrigger
  102. //---------------------------------------------------------------------------------------------------------------------
  103. bool EventManager::VTriggerEvent(const IEventDataPtr& pEvent) const
  104. {
  105. GCC_LOG("Events", "Attempting to trigger event " + std::string(pEvent->GetName()));
  106. bool processed = false;
  107. auto findIt = m_eventListeners.find(pEvent->VGetEventType());
  108. if (findIt != m_eventListeners.end())
  109. {
  110. const EventListenerList& eventListenerList = findIt->second;
  111. for (EventListenerList::const_iterator it = eventListenerList.begin(); it != eventListenerList.end(); ++it)
  112. {
  113. EventListenerDelegate listener = (*it);
  114. GCC_LOG("Events", "Sending Event " + std::string(pEvent->GetName()) + " to delegate.");
  115. listener(pEvent); // call the delegate
  116. processed = true;
  117. }
  118. }
  119. return processed;
  120. }
  121. //---------------------------------------------------------------------------------------------------------------------
  122. // EventManager::VQueueEvent
  123. //---------------------------------------------------------------------------------------------------------------------
  124. bool EventManager::VQueueEvent(const IEventDataPtr& pEvent)
  125. {
  126. GCC_ASSERT(m_activeQueue >= 0);
  127. GCC_ASSERT(m_activeQueue < EVENTMANAGER_NUM_QUEUES);
  128. // make sure the event is valid
  129. if (!pEvent)
  130. {
  131. GCC_ERROR("Invalid event in VQueueEvent()");
  132. return false;
  133. }
  134. GCC_LOG("Events", "Attempting to queue event: " + std::string(pEvent->GetName()));
  135. auto findIt = m_eventListeners.find(pEvent->VGetEventType());
  136. if (findIt != m_eventListeners.end())
  137. {
  138. m_queues[m_activeQueue].push_back(pEvent);
  139. GCC_LOG("Events", "Successfully queued event: " + std::string(pEvent->GetName()));
  140. return true;
  141. }
  142. else
  143. {
  144. GCC_LOG("Events", "Skipping event since there are no delegates registered to receive it: " + std::string(pEvent->GetName()));
  145. return false;
  146. }
  147. }
  148. //---------------------------------------------------------------------------------------------------------------------
  149. // EventManager::VTick
  150. //---------------------------------------------------------------------------------------------------------------------
  151. bool EventManager::VUpdate(unsigned long maxMillis)
  152. {
  153. unsigned long currMs = SDL_GetTicks();
  154. unsigned long maxMs = ((maxMillis == IEventManager::kINFINITE) ? (IEventManager::kINFINITE) : (currMs + maxMillis));
  155. // This section added to handle events from other threads. Check out Chapter 20.
  156. // IEventDataPtr pRealtimeEvent;
  157. // while (m_realtimeEventQueue.try_pop(pRealtimeEvent))
  158. // {
  159. // VQueueEvent(pRealtimeEvent);
  160. // currMs = SDL_GetTicks();
  161. // if (maxMillis != IEventManager::kInfinite)
  162. // {
  163. // if (currMs >= maxMs)
  164. // {
  165. // GCC_ERROR("A realtime process is spamming the event manager");
  166. // }
  167. // }
  168. // }
  169. // swap active queues and clear the new queue after the swap
  170. int queueToProcess = m_activeQueue;
  171. m_activeQueue = (m_activeQueue + 1) % EVENTMANAGER_NUM_QUEUES;
  172. m_queues[m_activeQueue].clear();
  173. GCC_LOG("EventLoop", "Processing Event Queue " + ToStr(queueToProcess) + "; " + ToStr((unsigned long)m_queues[queueToProcess].size()) + " events to process");
  174. // process the queue
  175. while (!m_queues[queueToProcess].empty())
  176. {
  177. // pop the front of the queue
  178. IEventDataPtr pEvent = m_queues[queueToProcess].front();
  179. m_queues[queueToProcess].pop_front();
  180. GCC_LOG("EventLoop", "\t\tProcessing Event " + std::string(pEvent->GetName()));
  181. const EventType& eventType = pEvent->VGetEventType();
  182. // find all the delegate functions registered for this event
  183. auto findIt = m_eventListeners.find(eventType);
  184. if (findIt != m_eventListeners.end())
  185. {
  186. const EventListenerList& eventListeners = findIt->second;
  187. GCC_LOG("EventLoop", "\t\tFound " + ToStr((unsigned long)eventListeners.size()) + " delegates");
  188. // call each listener
  189. for (auto it = eventListeners.begin(); it != eventListeners.end(); ++it)
  190. {
  191. EventListenerDelegate listener = (*it);
  192. GCC_LOG("EventLoop", "\t\tSending event " + std::string(pEvent->GetName()) + " to delegate");
  193. listener(pEvent);
  194. }
  195. }
  196. // check to see if time ran out
  197. currMs = SDL_GetTicks();
  198. if (maxMillis != IEventManager::kINFINITE && currMs >= maxMs)
  199. {
  200. GCC_LOG("EventLoop", "Aborting event processing; time ran out");
  201. break;
  202. }
  203. }
  204. // If we couldn't process all of the events, push the remaining events to the new active queue.
  205. // Note: To preserve sequencing, go back-to-front inserting them at the head of the active queue
  206. bool queueFlushed = (m_queues[queueToProcess].empty());
  207. if (!queueFlushed)
  208. {
  209. while (!m_queues[queueToProcess].empty())
  210. {
  211. IEventDataPtr pEvent = m_queues[queueToProcess].back();
  212. m_queues[queueToProcess].pop_back();
  213. m_queues[m_activeQueue].push_front(pEvent);
  214. }
  215. }
  216. return queueFlushed;
  217. }