Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
5.0 KiB

  1. //===== Copyright � 1996-2009, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "mm_events.h"
  7. // memdbgon must be the last include file in a .cpp file!!!
  8. #include "tier0/memdbgon.h"
  9. CMatchEventsSubscription::CMatchEventsSubscription() :
  10. m_bAllowNestedBroadcasts( false ),
  11. m_bBroadcasting( false )
  12. {
  13. ;
  14. }
  15. CMatchEventsSubscription::~CMatchEventsSubscription()
  16. {
  17. ;
  18. }
  19. static CMatchEventsSubscription g_MatchEventsSubscription;
  20. CMatchEventsSubscription *g_pMatchEventsSubscription = &g_MatchEventsSubscription;
  21. //
  22. // Implementation
  23. //
  24. void CMatchEventsSubscription::Subscribe( IMatchEventsSink *pSink )
  25. {
  26. if ( !pSink )
  27. return;
  28. int idx = m_arrSinks.Find( pSink );
  29. if ( m_arrSinks.IsValidIndex( idx ) )
  30. {
  31. Assert( m_arrRefCount.IsValidIndex( idx ) );
  32. Assert( m_arrRefCount[ idx ] > 0 );
  33. ++ m_arrRefCount[ idx ];
  34. }
  35. else
  36. {
  37. m_arrSinks.AddToTail( pSink );
  38. m_arrRefCount.AddToTail( 1 );
  39. Assert( m_arrSinks.Count() == m_arrRefCount.Count() );
  40. }
  41. }
  42. void CMatchEventsSubscription::Unsubscribe( IMatchEventsSink *pSink )
  43. {
  44. if ( !pSink )
  45. return;
  46. int idx = m_arrSinks.Find( pSink );
  47. Assert( m_arrSinks.IsValidIndex( idx ) );
  48. if ( !m_arrSinks.IsValidIndex( idx ) )
  49. return;
  50. Assert( m_arrRefCount.IsValidIndex( idx ) );
  51. Assert( m_arrRefCount[ idx ] > 0 );
  52. -- m_arrRefCount[ idx ];
  53. if ( m_arrRefCount[ idx ] <= 0 )
  54. {
  55. m_arrSinks.Remove( idx );
  56. m_arrRefCount.Remove( idx );
  57. Assert( m_arrSinks.Count() == m_arrRefCount.Count() );
  58. // Update outstanding iterators that are beyond removal point
  59. for ( int k = 0; k < m_arrIteratorsOutstanding.Count(); ++ k )
  60. {
  61. if ( m_arrIteratorsOutstanding[k] >= idx )
  62. -- m_arrIteratorsOutstanding[k];
  63. }
  64. }
  65. }
  66. void CMatchEventsSubscription::Shutdown()
  67. {
  68. m_bBroadcasting = true; // Blocks all BroadcastEvent calls from being dispatched!
  69. }
  70. void CMatchEventsSubscription::BroadcastEvent( KeyValues *pEvent )
  71. {
  72. //
  73. // Network raw packet decryption
  74. //
  75. if ( !Q_stricmp( "OnNetLanConnectionlessPacket", pEvent->GetName() ) )
  76. {
  77. if ( void * pRawPacket = pEvent->GetPtr( "rawpkt" ) )
  78. {
  79. netpacket_t *pkt = ( netpacket_t * ) pRawPacket;
  80. pEvent->deleteThis();
  81. g_pConnectionlessLanMgr->ProcessConnectionlessPacket( pkt );
  82. return;
  83. }
  84. }
  85. //
  86. // Broadcasting events is reliable even when subscribers get added
  87. // or removed during broadcasts, or even broadcast nested events.
  88. //
  89. // Nested broadcasts are not allowed because it messes up the perception
  90. // of event timeline by external listeners, nested broadcast is enqueued
  91. // instead and broadcast after the original event has been broadcast to
  92. // all subscribers.
  93. //
  94. if ( m_bBroadcasting )
  95. {
  96. if ( !m_bAllowNestedBroadcasts )
  97. {
  98. m_arrQueuedEvents.AddToTail( pEvent );
  99. return;
  100. }
  101. }
  102. m_bBroadcasting = true;
  103. KeyValues::AutoDelete autoDeleteEvent( pEvent );
  104. m_arrSentEvents.AddToHead( pEvent );
  105. // Internally events are cracked before external subscribers
  106. g_pMMF->OnEvent( pEvent );
  107. // iterate subscribers
  108. for ( m_arrIteratorsOutstanding.AddToTail( 0 );
  109. m_arrIteratorsOutstanding.Tail() < m_arrSinks.Count();
  110. ++ m_arrIteratorsOutstanding.Tail() )
  111. {
  112. int i = m_arrIteratorsOutstanding.Tail();
  113. IMatchEventsSink *pSink = m_arrSinks[ i ];
  114. Assert( m_arrRefCount.IsValidIndex( i ) );
  115. Assert( m_arrRefCount[i] > 0 );
  116. Assert( pSink );
  117. pSink->OnEvent( pEvent );
  118. }
  119. m_arrIteratorsOutstanding.RemoveMultipleFromTail( 1 );
  120. m_bBroadcasting = false;
  121. //
  122. // Broadcast queued events
  123. //
  124. if ( m_arrQueuedEvents.Count() > 0 )
  125. {
  126. KeyValues *pQueued = m_arrQueuedEvents.Head();
  127. m_arrQueuedEvents.RemoveMultipleFromHead( 1 );
  128. BroadcastEvent( pQueued );
  129. return;
  130. }
  131. //
  132. // No more queued events left, clean up registered event data
  133. //
  134. for ( int k = 0; k < m_arrEventData.Count(); ++ k )
  135. {
  136. KeyValues *pRegistered = m_arrEventData[k];
  137. pRegistered->deleteThis();
  138. }
  139. m_arrEventData.Purge();
  140. m_arrSentEvents.Purge();
  141. }
  142. void CMatchEventsSubscription::RegisterEventData( KeyValues *pEventData )
  143. {
  144. Assert( pEventData );
  145. if ( !pEventData )
  146. return;
  147. Assert( m_bBroadcasting );
  148. char const *szEventDataKey = pEventData->GetName();
  149. Assert( szEventDataKey && *szEventDataKey );
  150. if ( !szEventDataKey || !*szEventDataKey )
  151. return;
  152. for ( int k = 0; k < m_arrEventData.Count(); ++ k )
  153. {
  154. KeyValues *&pRegistered = m_arrEventData[k];
  155. if ( !Q_stricmp( szEventDataKey, pRegistered->GetName() ) )
  156. {
  157. pRegistered->deleteThis();
  158. pRegistered = pEventData;
  159. return;
  160. }
  161. }
  162. m_arrEventData.AddToTail( pEventData );
  163. }
  164. KeyValues * CMatchEventsSubscription::GetEventData( char const *szEventDataKey )
  165. {
  166. Assert( m_bBroadcasting );
  167. for ( int k = 0; k < m_arrEventData.Count(); ++ k )
  168. {
  169. KeyValues *pRegistered = m_arrEventData[k];
  170. if ( !Q_stricmp( szEventDataKey, pRegistered->GetName() ) )
  171. return pRegistered;
  172. }
  173. for ( int k = 0; k < m_arrSentEvents.Count(); ++ k )
  174. {
  175. KeyValues *pRegistered = m_arrSentEvents[k];
  176. if ( !Q_stricmp( szEventDataKey, pRegistered->GetName() ) )
  177. return pRegistered;
  178. }
  179. return NULL;
  180. }