diff --git a/src/ActorUtil.cpp b/src/ActorUtil.cpp index 253b372e8a..d7068672ab 100644 --- a/src/ActorUtil.cpp +++ b/src/ActorUtil.cpp @@ -14,26 +14,22 @@ // Actor registration -map & GetActorUtilRegistrees() -{ - static map registrees; - return registrees; -} +static map *g_pmapRegistrees = NULL; static bool IsRegistered( const RString& sClassName ) { - map & registrees = GetActorUtilRegistrees(); - return registrees.find( sClassName ) != registrees.end(); + return g_pmapRegistrees->find( sClassName ) != g_pmapRegistrees->end(); } void ActorUtil::Register( const RString& sClassName, CreateActorFn pfn ) { - map & registrees = GetActorUtilRegistrees(); + if( g_pmapRegistrees == NULL ) + g_pmapRegistrees = new map; - map::iterator iter = registrees.find( sClassName ); - ASSERT_M( iter == registrees.end(), ssprintf("Actor class '%s' already registered.", sClassName.c_str()) ); + map::iterator iter = g_pmapRegistrees->find( sClassName ); + ASSERT_M( iter == g_pmapRegistrees->end(), ssprintf("Actor class '%s' already registered.", sClassName.c_str()) ); - registrees[sClassName] = pfn; + (*g_pmapRegistrees)[sClassName] = pfn; } bool ActorUtil::ResolvePath( RString &sPath, const RString &sName ) @@ -123,10 +119,8 @@ Actor* ActorUtil::LoadFromNode( const XNode* pNode, Actor *pParentActor ) if( !bHasClass ) bHasClass = pNode->GetAttrValue( "Type", sClass ); - map & registrees = GetActorUtilRegistrees(); - - map::iterator iter = registrees.find( sClass ); - if( iter == registrees.end() ) + map::iterator iter = g_pmapRegistrees->find( sClass ); + if( iter == g_pmapRegistrees->end() ) { // sClass is invalid RString sError = ssprintf( "%s: invalid Class \"%s\"", diff --git a/src/Font.cpp b/src/Font.cpp index e0c3841bbc..a2f9824993 100644 --- a/src/Font.cpp +++ b/src/Font.cpp @@ -741,6 +741,8 @@ void Font::Load( const RString &sIniPath, RString sChars ) { const RString &sTexturePath = asTexturePaths[i]; + FontPage *pPage = new FontPage; + // Grab the page name, eg "foo" from "Normal [foo].png". RString sPagename = GetPageNameFromFileName( sTexturePath ); @@ -748,9 +750,6 @@ void Font::Load( const RString &sIniPath, RString sChars ) if( sTexturePath.find("-stroke") != string::npos ) continue; - // Create this down here so it doesn't leak if the continue gets triggered. - FontPage *pPage = new FontPage; - // Load settings for this page from the INI. FontPageSettings cfg; LoadFontPageSettings( cfg, ini, sTexturePath, "common", sChars ); diff --git a/src/LifeMeterTime.cpp b/src/LifeMeterTime.cpp index a113d26fae..d2eba75565 100644 --- a/src/LifeMeterTime.cpp +++ b/src/LifeMeterTime.cpp @@ -48,12 +48,6 @@ LifeMeterTime::LifeMeterTime() { m_fLifeTotalGainedSeconds = 0; m_fLifeTotalLostSeconds = 0; - m_pStream = NULL; -} - -LifeMeterTime::~LifeMeterTime() -{ - delete m_pStream; } void LifeMeterTime::Load( const PlayerState *pPlayerState, PlayerStageStats *pPlayerStageStats ) diff --git a/src/LifeMeterTime.h b/src/LifeMeterTime.h index c975286739..d2bd54e69c 100644 --- a/src/LifeMeterTime.h +++ b/src/LifeMeterTime.h @@ -16,8 +16,6 @@ class LifeMeterTime : public LifeMeter public: LifeMeterTime(); - virtual ~LifeMeterTime(); - virtual void Load( const PlayerState *pPlayerState, PlayerStageStats *pPlayerStageStats ); virtual void Update( float fDeltaTime ); diff --git a/src/LocalizedString.cpp b/src/LocalizedString.cpp index 251c043faf..bca6844c3a 100644 --- a/src/LocalizedString.cpp +++ b/src/LocalizedString.cpp @@ -4,11 +4,7 @@ #include "RageUtil.h" #include "SubscriptionManager.h" -SubscriptionManager & GetLocalizedSubscribers() -{ - static SubscriptionManager subscribers; - return subscribers; -} +static SubscriptionManager m_Subscribers; class LocalizedStringImplDefault: public ILocalizedStringImpl { @@ -31,7 +27,7 @@ static LocalizedString::MakeLocalizer g_pMakeLocalizedStringImpl = LocalizedStri void LocalizedString::RegisterLocalizer( MakeLocalizer pFunc ) { g_pMakeLocalizedStringImpl = pFunc; - FOREACHS( LocalizedString*, GetLocalizedSubscribers().m_pSubscribers, l ) + FOREACHS( LocalizedString*, *m_Subscribers.m_pSubscribers, l ) { LocalizedString *pLoc = *l; pLoc->CreateImpl(); @@ -40,7 +36,7 @@ void LocalizedString::RegisterLocalizer( MakeLocalizer pFunc ) LocalizedString::LocalizedString( const RString& sGroup, const RString& sName ) { - GetLocalizedSubscribers().Subscribe( this ); + m_Subscribers.Subscribe( this ); m_sGroup = sGroup; m_sName = sName; @@ -51,7 +47,7 @@ LocalizedString::LocalizedString( const RString& sGroup, const RString& sName ) LocalizedString::~LocalizedString() { - GetLocalizedSubscribers().Unsubscribe( this ); + m_Subscribers.Unsubscribe( this ); SAFE_DELETE( m_pImpl ); } diff --git a/src/LuaBinding.cpp b/src/LuaBinding.cpp index ee36d4ca95..a264675164 100644 --- a/src/LuaBinding.cpp +++ b/src/LuaBinding.cpp @@ -5,25 +5,18 @@ #include "Foreach.h" #include "SubscriptionManager.h" - -SubscriptionManager & GetBindingSubscribers() -{ - static SubscriptionManager subscribers; - return subscribers; -} +static SubscriptionManager m_Subscribers; namespace { void RegisterTypes( lua_State *L ) { - SubscriptionManager & subscribers = GetBindingSubscribers(); - - if( subscribers.m_pSubscribers.empty() ) + if( m_Subscribers.m_pSubscribers == NULL ) return; /* Register base classes first. */ map mapToRegister; - FOREACHS( LuaBinding*, subscribers.m_pSubscribers, p ) + FOREACHS( LuaBinding*, *m_Subscribers.m_pSubscribers, p ) mapToRegister[(*p)->GetClassName()] = (*p); set setRegisteredAlready; @@ -66,12 +59,12 @@ REGISTER_WITH_LUA_FUNCTION( RegisterTypes ); LuaBinding::LuaBinding() { - GetBindingSubscribers().Subscribe( this ); + m_Subscribers.Subscribe( this ); } LuaBinding::~LuaBinding() { - GetBindingSubscribers().Unsubscribe( this ); + m_Subscribers.Unsubscribe( this ); } void LuaBinding::Register( lua_State *L ) diff --git a/src/LuaManager.cpp b/src/LuaManager.cpp index 77e36614c6..7bbe533d67 100644 --- a/src/LuaManager.cpp +++ b/src/LuaManager.cpp @@ -226,17 +226,17 @@ static int LuaPanic( lua_State *L ) } // Actor registration -vector & GetRegisteredActorTypes() -{ - static vector registeredActorTypes; - return registeredActorTypes; -} +static vector *g_vRegisterActorTypes = NULL; void LuaManager::Register( RegisterWithLuaFn pfn ) { - GetRegisteredActorTypes().push_back( pfn ); + if( g_vRegisterActorTypes == NULL ) + g_vRegisterActorTypes = new vector; + + g_vRegisterActorTypes->push_back( pfn ); } + LuaManager::LuaManager() { pImpl = new Impl; @@ -360,12 +360,13 @@ void LuaManager::RegisterTypes() { Lua *L = Get(); - vector & registeredActorTypes = GetRegisteredActorTypes(); - - for( unsigned i=0; isize(); i++ ) + { + RegisterWithLuaFn fn = (*g_vRegisterActorTypes)[i]; + fn( L ); + } } Release( L ); diff --git a/src/MenuTimer.cpp b/src/MenuTimer.cpp index 066b593e29..59e420a799 100644 --- a/src/MenuTimer.cpp +++ b/src/MenuTimer.cpp @@ -22,11 +22,6 @@ MenuTimer::MenuTimer() WARNING_COMMAND = NULL; } -MenuTimer::~MenuTimer() -{ - delete WARNING_COMMAND; -} - void MenuTimer::Load( RString sMetricsGroup ) { m_sprFrame.Load( THEME->GetPathG(sMetricsGroup, "Frame") ); diff --git a/src/MenuTimer.h b/src/MenuTimer.h index f95c5c5c1b..cd3a211c54 100644 --- a/src/MenuTimer.h +++ b/src/MenuTimer.h @@ -15,7 +15,6 @@ class MenuTimer : public ActorFrame { public: MenuTimer(); - virtual ~MenuTimer(); void Load( RString sMetricsGroup ); virtual void Update( float fDeltaTime ); diff --git a/src/Preference.cpp b/src/Preference.cpp index 7d417c44b1..50792ed0b5 100644 --- a/src/Preference.cpp +++ b/src/Preference.cpp @@ -7,27 +7,23 @@ #include "SubscriptionManager.h" #include "Foreach.h" -SubscriptionManager & GetPreferenceSubscribers() -{ - static SubscriptionManager subscribers; - return subscribers; -} +static SubscriptionManager m_Subscribers; IPreference::IPreference( const RString& sName ): m_sName( sName ), m_bIsStatic( false ) { - GetPreferenceSubscribers().Subscribe( this ); + m_Subscribers.Subscribe( this ); } IPreference::~IPreference() { - GetPreferenceSubscribers().Unsubscribe( this ); + m_Subscribers.Unsubscribe( this ); } IPreference *IPreference::GetPreferenceByName( const RString &sName ) { - FOREACHS( IPreference*, GetPreferenceSubscribers().m_pSubscribers, p ) + FOREACHS( IPreference*, *m_Subscribers.m_pSubscribers, p ) { if( !(*p)->GetName().CompareNoCase( sName ) ) return *p; @@ -38,20 +34,20 @@ IPreference *IPreference::GetPreferenceByName( const RString &sName ) void IPreference::LoadAllDefaults() { - FOREACHS_CONST( IPreference*, GetPreferenceSubscribers().m_pSubscribers, p ) + FOREACHS_CONST( IPreference*, *m_Subscribers.m_pSubscribers, p ) (*p)->LoadDefault(); } void IPreference::ReadAllPrefsFromNode( const XNode* pNode, bool bIsStatic ) { ASSERT( pNode != NULL ); - FOREACHS_CONST( IPreference*, GetPreferenceSubscribers().m_pSubscribers, p ) + FOREACHS_CONST( IPreference*, *m_Subscribers.m_pSubscribers, p ) (*p)->ReadFrom( pNode, bIsStatic ); } void IPreference::SavePrefsToNode( XNode* pNode ) { - FOREACHS_CONST( IPreference*, GetPreferenceSubscribers().m_pSubscribers, p ) + FOREACHS_CONST( IPreference*, *m_Subscribers.m_pSubscribers, p ) (*p)->WriteTo( pNode ); } @@ -59,7 +55,7 @@ void IPreference::ReadAllDefaultsFromNode( const XNode* pNode ) { if( pNode == NULL ) return; - FOREACHS_CONST( IPreference*, GetPreferenceSubscribers().m_pSubscribers, p ) + FOREACHS_CONST( IPreference*, *m_Subscribers.m_pSubscribers, p ) (*p)->ReadDefaultFrom( pNode ); } diff --git a/src/RageSoundReader_Resample_Good.cpp b/src/RageSoundReader_Resample_Good.cpp index eb705efa1d..ecc176c108 100644 --- a/src/RageSoundReader_Resample_Good.cpp +++ b/src/RageSoundReader_Resample_Good.cpp @@ -11,7 +11,6 @@ #include "RageUtil.h" #include "RageMath.h" #include "RageThreads.h" -#include "RageUtil_AutoPtr.h" #include @@ -398,28 +397,25 @@ int PolyphaseFilter::NumInputsForOutputSamples( const State &State, int iOut, in return iIn; } /** @brief Utilities for working with the PolyphaseFilter cache. */ -typedef AutoPtrCopyOnWrite PolyphaseFilterAutoPtr; namespace PolyphaseFilterCache { /* Cache filter data, and reuse it without copying. All operations after creation * are const, so this doesn't cause thread-safety problems. */ - typedef map, PolyphaseFilterAutoPtr> FilterMap; + typedef map, PolyphaseFilter *> FilterMap; static RageMutex PolyphaseFiltersLock("PolyphaseFiltersLock"); static FilterMap g_mapPolyphaseFilters; - const PolyphaseFilterAutoPtr MakePolyphaseFilter( int iUpFactor, float fCutoffFrequency ) + const PolyphaseFilter *MakePolyphaseFilter( int iUpFactor, float fCutoffFrequency ) { - PolyphaseFilterAutoPtr result; - PolyphaseFiltersLock.Lock(); pair params( make_pair(iUpFactor, fCutoffFrequency) ); FilterMap::const_iterator it = g_mapPolyphaseFilters.find(params); if( it != g_mapPolyphaseFilters.end() ) { /* We already have a filter for this upsampling factor and cutoff; use it. */ - result = it->second; + PolyphaseFilter *pPolyphase = it->second; PolyphaseFiltersLock.Unlock(); - return result; + return pPolyphase; } int iWinSize = L*iUpFactor; float *pFIR = new float[iWinSize]; @@ -432,14 +428,12 @@ namespace PolyphaseFilterCache pPolyphase->Generate( pFIR ); delete [] pFIR; - result = PolyphaseFilterAutoPtr(pPolyphase); - - g_mapPolyphaseFilters[params] = result; + g_mapPolyphaseFilters[params] = pPolyphase; PolyphaseFiltersLock.Unlock(); - return result; + return pPolyphase; } - const PolyphaseFilterAutoPtr FindNearestPolyphaseFilter( int iUpFactor, float fCutoffFrequency ) + const PolyphaseFilter *FindNearestPolyphaseFilter( int iUpFactor, float fCutoffFrequency ) { /* Find a cached filter with the same iUpFactor and a nearby cutoff frequency. * Round the cutoff down, if possible; it's better to filter out too much than @@ -450,7 +444,7 @@ namespace PolyphaseFilterCache if( it != g_mapPolyphaseFilters.begin() ) --it; ASSERT( it->first.first == iUpFactor ); - PolyphaseFilterAutoPtr pPolyphase = it->second; + PolyphaseFilter *pPolyphase = it->second; PolyphaseFiltersLock.Unlock(); return pPolyphase; } @@ -473,7 +467,7 @@ public: * when filtering. This will only cause the low-pass filter to be rounded; * the conversion ratio will always be exact. */ m_iUpFactor = iUpFactor; - m_pPolyphase = PolyphaseFilterAutoPtr(NULL); + m_pPolyphase = NULL; int iFilterIncrement = max( (iMaxDownFactor - iMinDownFactor)/10, 1 ); for( int iDownFactor = iMinDownFactor; iDownFactor <= iMaxDownFactor; iDownFactor += iFilterIncrement ) @@ -538,13 +532,13 @@ private: return fCutoffFrequency; } - const PolyphaseFilterAutoPtr GetFilter( int iDownFactor ) const + const PolyphaseFilter *GetFilter( int iDownFactor ) const { float fCutoffFrequency = GetCutoffFrequency( iDownFactor ); return PolyphaseFilterCache::FindNearestPolyphaseFilter( m_iUpFactor, fCutoffFrequency ); } - PolyphaseFilterAutoPtr m_pPolyphase; + const PolyphaseFilter *m_pPolyphase; PolyphaseFilter::State *m_pState; int m_iUpFactor; int m_iDownFactor; diff --git a/src/RageThreads.cpp b/src/RageThreads.cpp index 6efb6ebf45..e3aeb6b946 100644 --- a/src/RageThreads.cpp +++ b/src/RageThreads.cpp @@ -138,8 +138,8 @@ struct ThreadSlot *g_pUnknownThreadSlot = NULL; * so possibly racing over them is harmless (simply using a stale thread ID, etc). */ static RageMutex &GetThreadSlotsLock() { - static RageMutex lock( "ThreadSlots" ); - return lock; + static RageMutex *pLock = new RageMutex( "ThreadSlots" ); + return *pLock; } static int FindEmptyThreadSlot() diff --git a/src/ScreenDebugOverlay.cpp b/src/ScreenDebugOverlay.cpp index 93a5be7c2c..1361f81ab7 100644 --- a/src/ScreenDebugOverlay.cpp +++ b/src/ScreenDebugOverlay.cpp @@ -52,18 +52,15 @@ static LocalizedString ON ( "ScreenDebugOverlay", "on" ); static LocalizedString OFF ( "ScreenDebugOverlay", "off" ); class IDebugLine; -vector & GetSubscribers() -{ - static vector subscribers; - return subscribers; -} - +static vector *g_pvpSubscribers = NULL; class IDebugLine { public: IDebugLine() { - GetSubscribers().push_back( this ); + if( g_pvpSubscribers == NULL ) + g_pvpSubscribers = new vector; + g_pvpSubscribers->push_back( this ); } virtual ~IDebugLine() { } enum Type { all_screens, gameplay_only }; @@ -218,7 +215,7 @@ void ScreenDebugOverlay::Init() map iNextDebugButton; int iNextGameplayButton = 0; - FOREACH( IDebugLine*, GetSubscribers(), p ) + FOREACH( IDebugLine*, *g_pvpSubscribers, p ) { RString sPageName = (*p)->GetPageName(); @@ -274,7 +271,7 @@ void ScreenDebugOverlay::Init() this->AddChild( p ); } - FOREACH_CONST( IDebugLine*, GetSubscribers(), p ) + FOREACH_CONST( IDebugLine*, *g_pvpSubscribers, p ) { { BitmapText *bt = new BitmapText; @@ -353,15 +350,13 @@ void ScreenDebugOverlay::UpdateText() m_vptextPages[iPage]->PlayCommand( (iPage == m_iCurrentPage) ? "GainFocus" : "LoseFocus" ); } - vector & subscribers = GetSubscribers(); - // todo: allow changing of various spacing/location things -aj int iOffset = 0; - FOREACH_CONST( IDebugLine*, subscribers, p ) + FOREACH_CONST( IDebugLine*, *g_pvpSubscribers, p ) { RString sPageName = (*p)->GetPageName(); - int i = p-subscribers.begin(); + int i = p-g_pvpSubscribers->begin(); float fY = LINE_START_Y + iOffset * LINE_SPACING; @@ -452,13 +447,11 @@ bool ScreenDebugOverlay::Input( const InputEventPlus &input ) return true; } - vector & subscribers = GetSubscribers(); - - FOREACH_CONST( IDebugLine*, subscribers, p ) + FOREACH_CONST( IDebugLine*, *g_pvpSubscribers, p ) { RString sPageName = (*p)->GetPageName(); - int i = p-subscribers.begin(); + int i = p-g_pvpSubscribers->begin(); // Gameplay buttons are available only in gameplay. Non-gameplay buttons // are only available when the screen is displayed. diff --git a/src/ScreenManager.cpp b/src/ScreenManager.cpp index a52836c07e..842a29b2f9 100644 --- a/src/ScreenManager.cpp +++ b/src/ScreenManager.cpp @@ -79,11 +79,7 @@ static Preference g_bDelayedScreenLoad( "DelayedScreenLoad", false ); //static Preference g_bPruneFonts( "PruneFonts", true ); // Screen registration -map & GetRegistrees() -{ - static map registrees; - return registrees; -} +static map *g_pmapRegistrees = NULL; /** @brief Utility functions for the ScreenManager. */ namespace ScreenManagerUtil @@ -223,12 +219,13 @@ using namespace ScreenManagerUtil; RegisterScreenClass::RegisterScreenClass( const RString& sClassName, CreateScreenFn pfn ) { - map & registrees = GetRegistrees(); + if( g_pmapRegistrees == NULL ) + g_pmapRegistrees = new map; - map::iterator iter = registrees.find( sClassName ); - ASSERT_M( iter == registrees.end(), ssprintf("Screen class '%s' already registered.", sClassName.c_str()) ); + map::iterator iter = g_pmapRegistrees->find( sClassName ); + ASSERT_M( iter == g_pmapRegistrees->end(), ssprintf("Screen class '%s' already registered.", sClassName.c_str()) ); - registrees[sClassName] = pfn; + (*g_pmapRegistrees)[sClassName] = pfn; } @@ -535,10 +532,8 @@ Screen* ScreenManager::MakeNewScreen( const RString &sScreenName ) RString sClassName = THEME->GetMetric( sScreenName,"Class" ); - map & registrees = GetRegistrees(); - - map::iterator iter = registrees.find( sClassName ); - if( iter == registrees.end() ) + map::iterator iter = g_pmapRegistrees->find( sClassName ); + if( iter == g_pmapRegistrees->end() ) RageException::Throw( "Screen \"%s\" has an invalid class \"%s\".", sScreenName.c_str(), sClassName.c_str() ); this->ZeroNextUpdate(); @@ -876,7 +871,7 @@ public: } static int SystemMessage( T* p, lua_State *L ) { p->SystemMessage( SArg(1) ); return 0; } static int ScreenIsPrepped( T* p, lua_State *L ) { lua_pushboolean( L, ScreenManagerUtil::ScreenIsPrepped( SArg(1) ) ); return 1; } - static int ScreenClassExists( T* p, lua_State *L ) { lua_pushboolean( L, GetRegistrees().find( SArg(1) ) != GetRegistrees().end() ); return 1; } + static int ScreenClassExists( T* p, lua_State *L ) { lua_pushboolean( L, g_pmapRegistrees->find( SArg(1) ) != g_pmapRegistrees->end() ); return 1; } static int AddNewScreenToTop( T* p, lua_State *L ) { ScreenMessage SM = SM_None; diff --git a/src/ScreenMessage.cpp b/src/ScreenMessage.cpp index aacff90ec7..572f177055 100644 --- a/src/ScreenMessage.cpp +++ b/src/ScreenMessage.cpp @@ -17,25 +17,22 @@ AutoScreenMessage(SM_Pause); AutoScreenMessage(SM_Success); AutoScreenMessage(SM_Failure); -map & GetScreenMessages() -{ - static map screenMessages; - return screenMessages; -} +static map *m_pScreenMessages; ScreenMessage ScreenMessageHelpers::ToScreenMessage( const RString &sName ) { - map & screenMessages = GetScreenMessages(); + if( m_pScreenMessages == NULL ) + m_pScreenMessages = new map; - if( screenMessages.find( sName ) == screenMessages.end() ) - screenMessages[sName] = (ScreenMessage)sName; + if( m_pScreenMessages->find( sName ) == m_pScreenMessages->end() ) + (*m_pScreenMessages)[sName] = (ScreenMessage)sName; - return screenMessages[sName]; + return (*m_pScreenMessages)[sName]; } RString ScreenMessageHelpers::ScreenMessageToString( ScreenMessage SM ) { - FOREACHM( RString, ScreenMessage, GetScreenMessages(), it ) + FOREACHM( RString, ScreenMessage, *m_pScreenMessages, it ) if( SM == it->second ) return (*it).first; diff --git a/src/StreamDisplay.cpp b/src/StreamDisplay.cpp index d6ddba882e..f278f92c1b 100644 --- a/src/StreamDisplay.cpp +++ b/src/StreamDisplay.cpp @@ -21,8 +21,6 @@ StreamDisplay::StreamDisplay() m_fPassingAlpha = 0; m_fHotAlpha = 0; m_bAlwaysBounce = false; - - m_bDeleteChildren = true; } void StreamDisplay::Load( const RString & /* unreferenced: _sMetricsGroup */) diff --git a/src/SubscriptionManager.h b/src/SubscriptionManager.h index 386760aa26..58ca1e5e46 100644 --- a/src/SubscriptionManager.h +++ b/src/SubscriptionManager.h @@ -5,36 +5,46 @@ #include -// When using this class be sure to use the global static initializer trick by wrapping the static object in a function like the -// following example: -// -// SubscriptionManager & GetSubscribers() -// { -// static SubscriptionManager subscribers; -// return subscribers; -// } -// -// This ensures that the object is always available when it's needed. +// Since this class has only POD types and no constructor, there's no +// initialize order problem. template class SubscriptionManager { public: - set m_pSubscribers; + // 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. SubscriptionHandler itself is + // a POD type, so a static SubscriptionHandler will always have + // m_pSubscribers == NULL (before any static constructors are called). + set* m_pSubscribers; + + // Use this to access m_pSubscribers, so you don't have to worry about + // it being NULL. + set &Get() + { + if( m_pSubscribers == NULL ) + m_pSubscribers = new set; + return *m_pSubscribers; + } void Subscribe( T* p ) { + if( m_pSubscribers == NULL ) + m_pSubscribers = new set; #ifdef DEBUG - typename set::iterator iter = m_pSubscribers.find( p ); - ASSERT_M( iter == m_pSubscribers.end(), "already subscribed" ); + typename set::iterator iter = m_pSubscribers->find( p ); + ASSERT_M( iter == m_pSubscribers->end(), "already subscribed" ); #endif - m_pSubscribers.insert( p ); + m_pSubscribers->insert( p ); } void Unsubscribe( T* p ) { - typename set::iterator iter = m_pSubscribers.find( p ); - ASSERT( iter != m_pSubscribers.end() ); - m_pSubscribers.erase( iter ); + typename set::iterator iter = m_pSubscribers->find( p ); + ASSERT( iter != m_pSubscribers->end() ); + m_pSubscribers->erase( iter ); } }; diff --git a/src/ThemeManager.cpp b/src/ThemeManager.cpp index 1b7248c13d..4a390ea901 100644 --- a/src/ThemeManager.cpp +++ b/src/ThemeManager.cpp @@ -63,12 +63,7 @@ LoadedThemeData *g_pLoadedThemeData = NULL; // For self-registering metrics #include "SubscriptionManager.h" - -SubscriptionManager & GetMetricSubscribers() -{ - static SubscriptionManager subscribers; - return subscribers; -} +static SubscriptionManager g_Subscribers; class LocalizedStringImplThemeMetric : public ILocalizedStringImpl, public ThemeMetric { @@ -100,7 +95,7 @@ public: void ThemeManager::Subscribe( IThemeMetric *p ) { - GetMetricSubscribers().Subscribe( p ); + g_Subscribers.Subscribe( p ); // It's ThemeManager's responsibility to make sure all of its subscribers // are updated with current data. If a metric is created after @@ -112,7 +107,7 @@ void ThemeManager::Subscribe( IThemeMetric *p ) void ThemeManager::Unsubscribe( IThemeMetric *p ) { - GetMetricSubscribers().Unsubscribe( p ); + g_Subscribers.Unsubscribe( p ); } @@ -434,14 +429,20 @@ void ThemeManager::SwitchThemeAndLanguage( const RString &sThemeName_, const RSt void ThemeManager::ReloadSubscribers() { // reload subscribers - FOREACHS_CONST( IThemeMetric*, GetMetricSubscribers().m_pSubscribers, p ) - (*p)->Read(); + if( g_Subscribers.m_pSubscribers ) + { + FOREACHS_CONST( IThemeMetric*, *g_Subscribers.m_pSubscribers, p ) + (*p)->Read(); + } } void ThemeManager::ClearSubscribers() { - FOREACHS_CONST( IThemeMetric*, GetMetricSubscribers().m_pSubscribers, p ) - (*p)->Clear(); + if( g_Subscribers.m_pSubscribers ) + { + FOREACHS_CONST( IThemeMetric*, *g_Subscribers.m_pSubscribers, p ) + (*p)->Clear(); + } } void ThemeManager::RunLuaScripts( const RString &sMask, bool bUseThemeDir ) diff --git a/src/ThemeMetric.h b/src/ThemeMetric.h index faa5d6e61c..a4073ffa1a 100644 --- a/src/ThemeMetric.h +++ b/src/ThemeMetric.h @@ -187,7 +187,6 @@ public: { Load( RString(), NULL, 0 ); } - virtual ~ThemeMetric1D() { } void Load( const RString& sGroup, MetricName1D pfn, size_t N ) { m_metric.resize( N ); diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 8518629df5..f1843de7bc 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -268,55 +268,28 @@ bool TimingData::IsFakeAtRow( int iNoteRow ) const * * Note that types whose SegmentEffectAreas are "Indefinite" are NULL here, * because they should never need to be used; we always have at least one such - * segment in the TimingData, and if not, we'll crash anyway. -- vyhd - * - * I've modified the dummy segments a bit to use a static function trick to make - * sure the objects gets destructed instead of leaking a bunch of pointers. - */ -TimingSegment * GetDummyTimingSegment( TimingSegmentType tst ) + * segment in the TimingData, and if not, we'll crash anyway. -- vyhd */ +static const TimingSegment* DummySegments[NUM_TimingSegmentType] = { - TimingSegment * result = NULL; - - switch( tst ) - { - case SEGMENT_STOP: - { - static StopSegment stopSegment; - result = &stopSegment; - break; - } - - case SEGMENT_DELAY: - { - static DelaySegment delaySegment; - result = &delaySegment; - break; - } - - case SEGMENT_WARP: - { - static WarpSegment warpSegment; - result = &warpSegment; - break; - } - - case SEGMENT_FAKE: - { - static FakeSegment fakeSegment; - result = &fakeSegment; - break; - } - } - - return result; -} + NULL, // BPMSegment + new StopSegment, + new DelaySegment, + NULL, // TimeSignatureSegment + new WarpSegment, + NULL, // LabelSegment + NULL, // TickcountSegment + NULL, // ComboSegment + NULL, // SpeedSegment + NULL, // ScrollSegment + new FakeSegment +}; const TimingSegment* TimingData::GetSegmentAtRow( int iNoteRow, TimingSegmentType tst ) const { const vector &vSegments = GetTimingSegments(tst); if( vSegments.empty() ) - return GetDummyTimingSegment(tst); + return DummySegments[tst]; int index = GetSegmentIndexAtRow( tst, iNoteRow ); const TimingSegment *seg = vSegments[index]; @@ -335,7 +308,7 @@ const TimingSegment* TimingData::GetSegmentAtRow( int iNoteRow, TimingSegmentTyp if( seg->GetRow() == iNoteRow ) return seg; else - return GetDummyTimingSegment(tst); + return DummySegments[tst]; } } diff --git a/src/arch/Dialog/DialogDriver.cpp b/src/arch/Dialog/DialogDriver.cpp index 03d850a330..4a2f7b4a04 100644 --- a/src/arch/Dialog/DialogDriver.cpp +++ b/src/arch/Dialog/DialogDriver.cpp @@ -3,11 +3,14 @@ #include "Foreach.h" #include "RageLog.h" +map *RegisterDialogDriver::g_pRegistrees; RegisterDialogDriver::RegisterDialogDriver( const istring &sName, CreateDialogDriverFn pfn ) { - map & registrees = GetRegistrees(); - ASSERT( registrees.find(sName) == registrees.end() ); - registrees[sName] = pfn; + if( g_pRegistrees == NULL ) + g_pRegistrees = new map; + + ASSERT( g_pRegistrees->find(sName) == g_pRegistrees->end() ); + (*g_pRegistrees)[sName] = pfn; } REGISTER_DIALOG_DRIVER_CLASS( Null ); @@ -20,13 +23,11 @@ DialogDriver *DialogDriver::Create() ASSERT( asDriversToTry.size() != 0 ); - map & registrees = RegisterDialogDriver::GetRegistrees(); - FOREACH_CONST( RString, asDriversToTry, Driver ) { - map::const_iterator iter = registrees.find( istring(*Driver) ); + map::const_iterator iter = RegisterDialogDriver::g_pRegistrees->find( istring(*Driver) ); - if( iter == registrees.end() ) + if( iter == RegisterDialogDriver::g_pRegistrees->end() ) continue; DialogDriver *pRet = (iter->second)(); diff --git a/src/arch/Dialog/DialogDriver.h b/src/arch/Dialog/DialogDriver.h index ff60e136a2..5e377328ba 100644 --- a/src/arch/Dialog/DialogDriver.h +++ b/src/arch/Dialog/DialogDriver.h @@ -25,12 +25,7 @@ class DialogDriver_Null : public DialogDriver { }; typedef DialogDriver *(*CreateDialogDriverFn)(); struct RegisterDialogDriver { - static map & GetRegistrees() - { - static map registrees; - return registrees; - } - + static map *g_pRegistrees; RegisterDialogDriver( const istring &sName, CreateDialogDriverFn pfn ); }; #define REGISTER_DIALOG_DRIVER_CLASS( name ) \ diff --git a/src/arch/InputHandler/InputHandler.cpp b/src/arch/InputHandler/InputHandler.cpp index 20bb126fdf..c8eca4eb26 100644 --- a/src/arch/InputHandler/InputHandler.cpp +++ b/src/arch/InputHandler/InputHandler.cpp @@ -164,6 +164,8 @@ RString InputHandler::GetLocalizedInputString( const DeviceInput &di ) } } +DriverList InputHandler::m_pDriverList; + static LocalizedString INPUT_HANDLERS_EMPTY( "Arch", "Input Handlers cannot be empty." ); void InputHandler::Create( const RString &drivers_, vector &Add ) { @@ -176,7 +178,7 @@ void InputHandler::Create( const RString &drivers_, vector &Add FOREACH_CONST( RString, DriversToTry, s ) { - RageDriver *pDriver = InputHandler::GetDriverList().Create( *s ); + RageDriver *pDriver = InputHandler::m_pDriverList.Create( *s ); if( pDriver == NULL ) { LOG->Trace( "Unknown Input Handler name: %s", s->c_str() ); diff --git a/src/arch/InputHandler/InputHandler.h b/src/arch/InputHandler/InputHandler.h index 7e4c18542d..2afaa75066 100644 --- a/src/arch/InputHandler/InputHandler.h +++ b/src/arch/InputHandler/InputHandler.h @@ -23,12 +23,7 @@ class InputHandler: public RageDriver { public: static void Create( const RString &sDrivers, vector &apAdd ); - - static DriverList & GetDriverList() - { - static DriverList driverList; - return driverList; - } + static DriverList m_pDriverList; InputHandler(): m_LastUpdate(), m_iInputsSinceUpdate(0) {} virtual ~InputHandler() { } @@ -74,7 +69,7 @@ private: }; #define REGISTER_INPUT_HANDLER_CLASS2( name, x ) \ - static RegisterRageDriver register_##name( &InputHandler::GetDriverList(), #name, CreateClass ) + static RegisterRageDriver register_##name( &InputHandler::m_pDriverList, #name, CreateClass ) #define REGISTER_INPUT_HANDLER_CLASS( name ) REGISTER_INPUT_HANDLER_CLASS2( name, name ) diff --git a/src/arch/Lights/LightsDriver.cpp b/src/arch/Lights/LightsDriver.cpp index 38b79350ae..0d48c59cad 100644 --- a/src/arch/Lights/LightsDriver.cpp +++ b/src/arch/Lights/LightsDriver.cpp @@ -4,6 +4,8 @@ #include "Foreach.h" #include "arch/arch_default.h" +DriverList LightsDriver::m_pDriverList; + void LightsDriver::Create( const RString &sDrivers, vector &Add ) { LOG->Trace( "Initializing lights drivers: %s", sDrivers.c_str() ); @@ -13,7 +15,7 @@ void LightsDriver::Create( const RString &sDrivers, vector &Add FOREACH_CONST( RString, asDriversToTry, Driver ) { - RageDriver *pRet = GetDriverList().Create( *Driver ); + RageDriver *pRet = m_pDriverList.Create( *Driver ); if( pRet == NULL ) { LOG->Trace( "Unknown lights driver: %s", Driver->c_str() ); diff --git a/src/arch/Lights/LightsDriver.h b/src/arch/Lights/LightsDriver.h index 145e453073..5420f25cf5 100644 --- a/src/arch/Lights/LightsDriver.h +++ b/src/arch/Lights/LightsDriver.h @@ -10,12 +10,7 @@ class LightsDriver: public RageDriver { public: static void Create( const RString &sDriver, vector &apAdd ); - - static DriverList & GetDriverList() - { - static DriverList driverList; - return driverList; - } + static DriverList m_pDriverList; LightsDriver() {}; virtual ~LightsDriver() {}; @@ -24,7 +19,7 @@ public: }; #define REGISTER_SOUND_DRIVER_CLASS2( name, x ) \ - static RegisterRageDriver register_##x( &LightsDriver::GetDriverList(), #name, CreateClass ) + static RegisterRageDriver register_##x( &LightsDriver::m_pDriverList, #name, CreateClass ) #define REGISTER_SOUND_DRIVER_CLASS( name ) REGISTER_SOUND_DRIVER_CLASS2( name, name ) #endif diff --git a/src/arch/MovieTexture/MovieTexture.cpp b/src/arch/MovieTexture/MovieTexture.cpp index e0fc9132ea..8c9190117f 100644 --- a/src/arch/MovieTexture/MovieTexture.cpp +++ b/src/arch/MovieTexture/MovieTexture.cpp @@ -62,6 +62,8 @@ bool RageMovieTexture::GetFourCC( RString fn, RString &handler, RString &type ) #undef HANDLE_ERROR } +DriverList RageMovieTextureDriver::m_pDriverList; + // Helper for MakeRageMovieTexture() static void DumpAVIDebugInfo( const RString& fn ) { @@ -95,7 +97,7 @@ RageMovieTexture *RageMovieTexture::Create( RageTextureID ID ) FOREACH_CONST( RString, DriversToTry, Driver ) { LOG->Trace( "Initializing driver: %s", Driver->c_str() ); - RageDriver *pDriverBase = RageMovieTextureDriver::GetDriverList().Create( *Driver ); + RageDriver *pDriverBase = RageMovieTextureDriver::m_pDriverList.Create( *Driver ); if( pDriverBase == NULL ) { diff --git a/src/arch/MovieTexture/MovieTexture.h b/src/arch/MovieTexture/MovieTexture.h index 9a29d03d74..4ab84e843c 100644 --- a/src/arch/MovieTexture/MovieTexture.h +++ b/src/arch/MovieTexture/MovieTexture.h @@ -32,15 +32,11 @@ class RageMovieTextureDriver: public RageDriver public: virtual ~RageMovieTextureDriver() { } virtual RageMovieTexture *Create( RageTextureID ID, RString &sError ) = 0; - static DriverList & GetDriverList() - { - static DriverList driverList; - return driverList; - } + static DriverList m_pDriverList; }; #define REGISTER_MOVIE_TEXTURE_CLASS( name ) \ - static RegisterRageDriver register_##name( &RageMovieTextureDriver::GetDriverList(), #name, CreateClass ) + static RegisterRageDriver register_##name( &RageMovieTextureDriver::m_pDriverList, #name, CreateClass ) #endif diff --git a/src/arch/RageDriver.cpp b/src/arch/RageDriver.cpp index d7782d577a..5301b1ec85 100644 --- a/src/arch/RageDriver.cpp +++ b/src/arch/RageDriver.cpp @@ -3,17 +3,20 @@ void DriverList::Add( const istring &sName, CreateRageDriverFn pfn ) { - ASSERT( m_pRegistrees.find(sName) == m_pRegistrees.end() ); - m_pRegistrees[sName] = pfn; + if( m_pRegistrees == NULL ) + m_pRegistrees = new map; + + ASSERT( m_pRegistrees->find(sName) == m_pRegistrees->end() ); + (*m_pRegistrees)[sName] = pfn; } RageDriver *DriverList::Create( const RString &sDriverName ) { - if( m_pRegistrees.empty()) + if( m_pRegistrees == NULL ) return NULL; - map::const_iterator iter = m_pRegistrees.find( istring(sDriverName) ); - if( iter == m_pRegistrees.end() ) + map::const_iterator iter = m_pRegistrees->find( istring(sDriverName) ); + if( iter == m_pRegistrees->end() ) return NULL; return (iter->second)(); } diff --git a/src/arch/RageDriver.h b/src/arch/RageDriver.h index 44b2b7a529..fa2f3a32ad 100644 --- a/src/arch/RageDriver.h +++ b/src/arch/RageDriver.h @@ -11,11 +11,12 @@ public: typedef RageDriver *(*CreateRageDriverFn)(); +/* This is created and accessed during C++ static initialization; it must be a POD. */ struct DriverList { void Add( const istring &sName, CreateRageDriverFn pfn ); RageDriver *Create( const RString &sDriverName ); - map m_pRegistrees; + map *m_pRegistrees; }; struct RegisterRageDriver diff --git a/src/arch/Sound/RageSoundDriver.cpp b/src/arch/Sound/RageSoundDriver.cpp index 9c263ba349..a491a5096f 100644 --- a/src/arch/Sound/RageSoundDriver.cpp +++ b/src/arch/Sound/RageSoundDriver.cpp @@ -5,6 +5,8 @@ #include "Foreach.h" #include "arch/arch_default.h" +DriverList RageSoundDriver::m_pDriverList; + RageSoundDriver *RageSoundDriver::Create( const RString& sDrivers ) { vector DriversToTry; @@ -12,7 +14,7 @@ RageSoundDriver *RageSoundDriver::Create( const RString& sDrivers ) FOREACH_CONST( RString, DriversToTry, Driver ) { - RageDriver *pDriver = GetDriverList().Create( *Driver ); + RageDriver *pDriver = m_pDriverList.Create( *Driver ); if( pDriver == NULL ) { LOG->Trace( "Unknown sound driver: %s", Driver->c_str() ); diff --git a/src/arch/Sound/RageSoundDriver.h b/src/arch/Sound/RageSoundDriver.h index a27a23810b..a377e10f0d 100644 --- a/src/arch/Sound/RageSoundDriver.h +++ b/src/arch/Sound/RageSoundDriver.h @@ -17,12 +17,7 @@ class RageSoundDriver: public RageDriver public: /* Pass an empty string to get the default sound driver list. */ static RageSoundDriver *Create( const RString &sDrivers ); - - static DriverList & GetDriverList() - { - static DriverList driverList; - return driverList; - } + static DriverList m_pDriverList; friend class RageSoundManager; @@ -214,7 +209,7 @@ private: // Can't use Create##name because many of these have -sw suffixes. #define REGISTER_SOUND_DRIVER_CLASS2( name, x ) \ - static RegisterRageDriver register_##x( &RageSoundDriver::GetDriverList(), #name, CreateClass ) + static RegisterRageDriver register_##x( &RageSoundDriver::m_pDriverList, #name, CreateClass ) #define REGISTER_SOUND_DRIVER_CLASS( name ) REGISTER_SOUND_DRIVER_CLASS2( name, name ) diff --git a/src/arch/Threads/Threads_Win32.cpp b/src/arch/Threads/Threads_Win32.cpp index 7cde15f42a..008d93597d 100644 --- a/src/arch/Threads/Threads_Win32.cpp +++ b/src/arch/Threads/Threads_Win32.cpp @@ -7,10 +7,12 @@ const int MAX_THREADS=128; -MutexImpl_Win32 & GetThreadMutex() +static MutexImpl_Win32 *g_pThreadIdMutex = NULL; +static void InitThreadIdMutex() { - static MutexImpl_Win32 mutex(NULL); - return mutex; + if( g_pThreadIdMutex != NULL ) + return; + g_pThreadIdMutex = new MutexImpl_Win32(NULL); } static uint64_t g_ThreadIds[MAX_THREADS]; @@ -106,9 +108,9 @@ static DWORD WINAPI StartThread( LPVOID pData ) static int GetOpenSlot( uint64_t iID ) { - MutexImpl_Win32 & mutex = GetThreadMutex(); + InitThreadIdMutex(); - mutex.Lock(); + g_pThreadIdMutex->Lock(); // Find an open slot in g_ThreadIds. int slot = 0; @@ -118,7 +120,7 @@ static int GetOpenSlot( uint64_t iID ) g_ThreadIds[slot] = iID; - mutex.Unlock(); + g_pThreadIdMutex->Unlock(); return slot; }