diff --git a/stepmania/src/ActorCommands.cpp b/stepmania/src/ActorCommands.cpp index c7aa657c40..4edc2082f8 100644 --- a/stepmania/src/ActorCommands.cpp +++ b/stepmania/src/ActorCommands.cpp @@ -7,21 +7,9 @@ #include "LuaManager.h" #include "LuaBinding.h" -static vector* g_pActorCommands; +#include "SubscriptionManager.h" +set* SubscriptionManager::s_pSubscribers = NULL; -static void Subscribe( ActorCommands* p ) -{ - if( g_pActorCommands == NULL ) - g_pActorCommands = new vector; - g_pActorCommands->push_back( p ); -} - -static void Unsubscribe( ActorCommands* p ) -{ - vector::iterator iter = find( g_pActorCommands->begin(), g_pActorCommands->end(), p ); - ASSERT( iter != g_pActorCommands->end() ); - g_pActorCommands->erase( iter ); -} static CString GetNextFunctionName() { @@ -32,7 +20,7 @@ static CString GetNextFunctionName() ActorCommands::ActorCommands( const Commands& cmds ) { - Subscribe( this ); + SubscriptionManager::Subscribe( this ); m_cmds = cmds; @@ -41,7 +29,7 @@ ActorCommands::ActorCommands( const Commands& cmds ) ActorCommands::~ActorCommands() { - Unsubscribe( this ); + SubscriptionManager::Unsubscribe( this ); if( m_sLuaFunctionName.size() ) Unregister(); @@ -49,7 +37,7 @@ ActorCommands::~ActorCommands() ActorCommands::ActorCommands( const ActorCommands& cpy ) { - Subscribe( this ); + SubscriptionManager::Subscribe( this ); m_sLuaFunctionName = GetNextFunctionName(); @@ -172,9 +160,9 @@ void ActorCommands::Unregister() void ActorCommands::ReRegisterAll() { - if( g_pActorCommands == NULL ) + if( SubscriptionManager::s_pSubscribers == NULL ) return; - FOREACH( ActorCommands*, *g_pActorCommands, p ) + FOREACHS( ActorCommands*, *SubscriptionManager::s_pSubscribers, p ) (*p)->Register(); } diff --git a/stepmania/src/PrefsManager.cpp b/stepmania/src/PrefsManager.cpp index 8765c88e36..122dbefcd8 100644 --- a/stepmania/src/PrefsManager.cpp +++ b/stepmania/src/PrefsManager.cpp @@ -24,31 +24,22 @@ const CString DEFAULT_LIGHTS_DRIVER = "Null"; // // For self-registering prefs // -static vector *g_pvpSubscribers = NULL; +#include "SubscriptionManager.h" +set* SubscriptionManager::s_pSubscribers = NULL; void PrefsManager::Subscribe( IPreference *p ) { - // TRICKY: If we make this a global vector instead of a global pointer, - // then we'd have to be careful that the static constructors of all - // Preferences are called before the vector constructor. It's - // too tricky to enfore that, so we'll allocate the vector ourself - // so that the compiler can't possibly call the vector constructor - // after we've already added to the vector. - if( g_pvpSubscribers == NULL ) - g_pvpSubscribers = new vector; - g_pvpSubscribers->push_back( p ); + SubscriptionManager::Subscribe( p ); } void PrefsManager::Unsubscribe( IPreference *p ) { - vector::iterator iter = find( g_pvpSubscribers->begin(), g_pvpSubscribers->end(), p ); - ASSERT( iter != g_pvpSubscribers->end() ); // tried to unregister when not registered - g_pvpSubscribers->erase( iter ); + SubscriptionManager::Unsubscribe( p ); } IPreference *PrefsManager::GetPreferenceByName( const CString &sName ) { - FOREACH( IPreference*, *g_pvpSubscribers, p ) + FOREACHS( IPreference*, *SubscriptionManager::s_pSubscribers, p ) { if( !(*p)->GetName().CompareNoCase( sName ) ) return *p; @@ -350,7 +341,8 @@ void PrefsManager::Init() m_bLogVirtualMemory = false; #endif - FOREACH_CONST( IPreference*, *g_pvpSubscribers, p ) (*p)->LoadDefault(); + FOREACHS_CONST( IPreference*, *SubscriptionManager::s_pSubscribers, p ) + (*p)->LoadDefault(); } PrefsManager::~PrefsManager() @@ -575,7 +567,8 @@ void PrefsManager::ReadPrefsFromFile( CString sIni ) ini.GetValue( "Debug", "LogCheckpoints", m_bLogCheckpoints ); ini.GetValue( "Debug", "ShowLoadingWindow", m_bShowLoadingWindow ); - FOREACH( IPreference*, *g_pvpSubscribers, p ) (*p)->ReadFrom( ini ); + FOREACHS_CONST( IPreference*, *SubscriptionManager::s_pSubscribers, p ) + (*p)->ReadFrom( ini ); } void PrefsManager::SaveGlobalPrefsToDisk() const @@ -819,7 +812,8 @@ void PrefsManager::SaveGlobalPrefsToDisk() const ini.SetValue( "Debug", "LogVirtualMemory", m_bLogVirtualMemory ); #endif - FOREACH_CONST( IPreference*, *g_pvpSubscribers, p ) (*p)->WriteTo( ini ); + FOREACHS_CONST( IPreference*, *SubscriptionManager::s_pSubscribers, p ) + (*p)->WriteTo( ini ); ini.WriteFile( STEPMANIA_INI_PATH ); } diff --git a/stepmania/src/SubscriptionManager.h b/stepmania/src/SubscriptionManager.h new file mode 100644 index 0000000000..b32f08c370 --- /dev/null +++ b/stepmania/src/SubscriptionManager.h @@ -0,0 +1,59 @@ +/* SubscriptionManager - Object that accepts subscriptions. */ + +#ifndef SubscriptionManager_H +#define SubscriptionManager_H + +#include +template +class SubscriptionManager +{ +public: + // TRICKY: If we make this a global instead of a global pointer, + // then we'd have to be careful that the static constructors of all + // subscribers are called before the collection constructor. It's + // impossible to enfore that in C++. Instead, we'll allocate the + // collection ourself on first use. + static set* s_pSubscribers; + + static void Subscribe( T* p ) + { + if( s_pSubscribers == NULL ) + s_pSubscribers = new set; + s_pSubscribers->insert( p ); + } + + static void Unsubscribe( T* p ) + { + set::iterator iter = s_pSubscribers->find( p ); + ASSERT( iter != s_pSubscribers->end() ); + s_pSubscribers->erase( iter ); + } + +}; + +#endif + +/* + * (c) 2001-2004 Chris Danford, Chris Gomez + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ diff --git a/stepmania/src/ThemeManager.cpp b/stepmania/src/ThemeManager.cpp index 576ded589d..186f46b10f 100644 --- a/stepmania/src/ThemeManager.cpp +++ b/stepmania/src/ThemeManager.cpp @@ -50,25 +50,15 @@ struct Theme deque g_vThemes; - - // // For self-registering metrics // -static vector *g_pvpSubscribers = NULL; +#include "SubscriptionManager.h" +set* SubscriptionManager::s_pSubscribers = NULL; void ThemeManager::Subscribe( IThemeMetric *p ) { - // TRICKY: If we make this a global vector instead of a global pointer, - // then we'd have to be careful that the static constructors of all - // Preferences are called before the vector constructor. It's - // too tricky to enfore that, so we'll allocate the vector ourself - // so that the compiler can't possibly call the vector constructor - // after we've already added to the vector. - if( g_pvpSubscribers == NULL ) - g_pvpSubscribers = new vector; - g_pvpSubscribers->push_back( p ); - + SubscriptionManager::Subscribe( p ); // It's ThemeManager's responsibility to make sure all of it's subscribers // are updated with current data. If a metric is created after @@ -80,13 +70,10 @@ void ThemeManager::Subscribe( IThemeMetric *p ) void ThemeManager::Unsubscribe( IThemeMetric *p ) { - vector::iterator iter = find( g_pvpSubscribers->begin(), g_pvpSubscribers->end(), p ); - ASSERT( iter != g_pvpSubscribers->end() ); // tried to unregister when not registered - g_pvpSubscribers->erase( iter ); + SubscriptionManager::Unsubscribe( p ); } - /* We spend a lot of time doing redundant theme path lookups. Cache results. */ static map g_ThemePathCache[NUM_ELEMENT_CATEGORIES]; @@ -272,7 +259,8 @@ void ThemeManager::SwitchThemeAndLanguage( const CString &sThemeName, const CStr UpdateLuaGlobals(); // reload subscribers - FOREACH( IThemeMetric*, *g_pvpSubscribers, p ) (*p)->Read(); + FOREACHS_CONST( IThemeMetric*, *SubscriptionManager::s_pSubscribers, p ) + (*p)->Read(); } void ThemeManager::UpdateLuaGlobals()