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.
|
|
//===== Copyright � 1996-2009, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "mm_events.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
CMatchEventsSubscription::CMatchEventsSubscription() : m_bAllowNestedBroadcasts( false ), m_bBroadcasting( false ) { ; }
CMatchEventsSubscription::~CMatchEventsSubscription() { ; }
static CMatchEventsSubscription g_MatchEventsSubscription; CMatchEventsSubscription *g_pMatchEventsSubscription = &g_MatchEventsSubscription;
//
// Implementation
//
void CMatchEventsSubscription::Subscribe( IMatchEventsSink *pSink ) { if ( !pSink ) return;
int idx = m_arrSinks.Find( pSink ); if ( m_arrSinks.IsValidIndex( idx ) ) { Assert( m_arrRefCount.IsValidIndex( idx ) ); Assert( m_arrRefCount[ idx ] > 0 ); ++ m_arrRefCount[ idx ]; } else { m_arrSinks.AddToTail( pSink ); m_arrRefCount.AddToTail( 1 ); Assert( m_arrSinks.Count() == m_arrRefCount.Count() ); } }
void CMatchEventsSubscription::Unsubscribe( IMatchEventsSink *pSink ) { if ( !pSink ) return;
int idx = m_arrSinks.Find( pSink ); Assert( m_arrSinks.IsValidIndex( idx ) ); if ( !m_arrSinks.IsValidIndex( idx ) ) return;
Assert( m_arrRefCount.IsValidIndex( idx ) ); Assert( m_arrRefCount[ idx ] > 0 );
-- m_arrRefCount[ idx ]; if ( m_arrRefCount[ idx ] <= 0 ) { m_arrSinks.Remove( idx ); m_arrRefCount.Remove( idx );
Assert( m_arrSinks.Count() == m_arrRefCount.Count() );
// Update outstanding iterators that are beyond removal point
for ( int k = 0; k < m_arrIteratorsOutstanding.Count(); ++ k ) { if ( m_arrIteratorsOutstanding[k] >= idx ) -- m_arrIteratorsOutstanding[k]; } } }
void CMatchEventsSubscription::Shutdown() { m_bBroadcasting = true; // Blocks all BroadcastEvent calls from being dispatched!
}
void CMatchEventsSubscription::BroadcastEvent( KeyValues *pEvent ) { //
// Network raw packet decryption
//
if ( !Q_stricmp( "OnNetLanConnectionlessPacket", pEvent->GetName() ) ) { if ( void * pRawPacket = pEvent->GetPtr( "rawpkt" ) ) { netpacket_t *pkt = ( netpacket_t * ) pRawPacket; pEvent->deleteThis(); g_pConnectionlessLanMgr->ProcessConnectionlessPacket( pkt ); return; } }
//
// Broadcasting events is reliable even when subscribers get added
// or removed during broadcasts, or even broadcast nested events.
//
// Nested broadcasts are not allowed because it messes up the perception
// of event timeline by external listeners, nested broadcast is enqueued
// instead and broadcast after the original event has been broadcast to
// all subscribers.
//
if ( m_bBroadcasting ) { if ( !m_bAllowNestedBroadcasts ) { m_arrQueuedEvents.AddToTail( pEvent ); return; } }
m_bBroadcasting = true;
KeyValues::AutoDelete autoDeleteEvent( pEvent ); m_arrSentEvents.AddToHead( pEvent );
// Internally events are cracked before external subscribers
g_pMMF->OnEvent( pEvent );
// iterate subscribers
for ( m_arrIteratorsOutstanding.AddToTail( 0 ); m_arrIteratorsOutstanding.Tail() < m_arrSinks.Count(); ++ m_arrIteratorsOutstanding.Tail() ) { int i = m_arrIteratorsOutstanding.Tail(); IMatchEventsSink *pSink = m_arrSinks[ i ]; Assert( m_arrRefCount.IsValidIndex( i ) ); Assert( m_arrRefCount[i] > 0 ); Assert( pSink );
pSink->OnEvent( pEvent ); } m_arrIteratorsOutstanding.RemoveMultipleFromTail( 1 );
m_bBroadcasting = false;
//
// Broadcast queued events
//
if ( m_arrQueuedEvents.Count() > 0 ) { KeyValues *pQueued = m_arrQueuedEvents.Head(); m_arrQueuedEvents.RemoveMultipleFromHead( 1 ); BroadcastEvent( pQueued ); return; }
//
// No more queued events left, clean up registered event data
//
for ( int k = 0; k < m_arrEventData.Count(); ++ k ) { KeyValues *pRegistered = m_arrEventData[k]; pRegistered->deleteThis(); } m_arrEventData.Purge(); m_arrSentEvents.Purge(); }
void CMatchEventsSubscription::RegisterEventData( KeyValues *pEventData ) { Assert( pEventData ); if ( !pEventData ) return;
Assert( m_bBroadcasting );
char const *szEventDataKey = pEventData->GetName(); Assert( szEventDataKey && *szEventDataKey ); if ( !szEventDataKey || !*szEventDataKey ) return;
for ( int k = 0; k < m_arrEventData.Count(); ++ k ) { KeyValues *&pRegistered = m_arrEventData[k]; if ( !Q_stricmp( szEventDataKey, pRegistered->GetName() ) ) { pRegistered->deleteThis(); pRegistered = pEventData; return; } }
m_arrEventData.AddToTail( pEventData ); }
KeyValues * CMatchEventsSubscription::GetEventData( char const *szEventDataKey ) { Assert( m_bBroadcasting );
for ( int k = 0; k < m_arrEventData.Count(); ++ k ) { KeyValues *pRegistered = m_arrEventData[k]; if ( !Q_stricmp( szEventDataKey, pRegistered->GetName() ) ) return pRegistered; }
for ( int k = 0; k < m_arrSentEvents.Count(); ++ k ) { KeyValues *pRegistered = m_arrSentEvents[k]; if ( !Q_stricmp( szEventDataKey, pRegistered->GetName() ) ) return pRegistered; }
return NULL; }
|