From feb919f0bf871a293adc67b87222abcb354ad738 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sat, 27 Apr 2013 00:05:14 -0400 Subject: [PATCH] Revert memory leak commits 5f7001e: "Added a new branch" 01456ed: "Fixed a lot of memory leaks" dac4493: "Fixed all remaining memory leaks that I could figure out" 0792db7: "Removed the smnew macro and the call to _CrtSetDbgFlag()" Some of these caused destructor-time problems due to static initialization order fiasco and related issues. Notably, the program would no longer exit on OSX and had to be killed. There were probably legitimate fixes in here, but since these are monolithic commits it's too much work to extract them now. Let's reapply them individually and in the forward direction. --- src/ActorUtil.cpp | 24 ++++------- src/Font.cpp | 5 +-- src/LifeMeterTime.cpp | 6 --- src/LifeMeterTime.h | 2 - src/LocalizedString.cpp | 12 ++---- src/LuaBinding.cpp | 17 +++----- src/LuaManager.cpp | 23 +++++----- src/MenuTimer.cpp | 5 --- src/MenuTimer.h | 1 - src/Preference.cpp | 20 ++++----- src/RageSoundReader_Resample_Good.cpp | 28 +++++------- src/RageThreads.cpp | 4 +- src/ScreenDebugOverlay.cpp | 27 +++++------- src/ScreenManager.cpp | 23 ++++------ src/ScreenMessage.cpp | 17 +++----- src/StreamDisplay.cpp | 2 - src/SubscriptionManager.h | 44 +++++++++++-------- src/ThemeManager.cpp | 25 +++++------ src/ThemeMetric.h | 1 - src/TimingData.cpp | 59 +++++++------------------- src/arch/Dialog/DialogDriver.cpp | 15 ++++--- src/arch/Dialog/DialogDriver.h | 7 +-- src/arch/InputHandler/InputHandler.cpp | 4 +- src/arch/InputHandler/InputHandler.h | 9 +--- src/arch/Lights/LightsDriver.cpp | 4 +- src/arch/Lights/LightsDriver.h | 9 +--- src/arch/MovieTexture/MovieTexture.cpp | 4 +- src/arch/MovieTexture/MovieTexture.h | 8 +--- src/arch/RageDriver.cpp | 13 +++--- src/arch/RageDriver.h | 3 +- src/arch/Sound/RageSoundDriver.cpp | 4 +- src/arch/Sound/RageSoundDriver.h | 9 +--- src/arch/Threads/Threads_Win32.cpp | 14 +++--- 33 files changed, 182 insertions(+), 266 deletions(-) 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; }