From fde9e0cfc94fd03b6564a5864ec77285f641f555 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Wed, 26 Jan 2005 20:52:20 +0000 Subject: [PATCH] auto_ptr is incompatible with STL containers; use a custom refcounted holder --- stepmania/src/ActorCommands.h | 4 +- stepmania/src/Makefile.am | 3 +- stepmania/src/RageUtil_AutoPtr.h | 122 +++++++++++++++++++++++++++++++ stepmania/src/StepMania.dsp | 8 +- stepmania/src/StepMania.vcproj | 3 + 5 files changed, 135 insertions(+), 5 deletions(-) create mode 100644 stepmania/src/RageUtil_AutoPtr.h diff --git a/stepmania/src/ActorCommands.h b/stepmania/src/ActorCommands.h index f8e845d1a0..8c730c2d56 100644 --- a/stepmania/src/ActorCommands.h +++ b/stepmania/src/ActorCommands.h @@ -3,7 +3,7 @@ #ifndef ActorCommands_H #define ActorCommands_H -#include // auto_ptr +#include "RageUtil_AutoPtr.h" class Commands; class ActorCommands @@ -22,7 +22,7 @@ private: CString m_sLuaFunctionName; }; -typedef auto_ptr apActorCommands; +typedef AutoPtrCopyOnWrite apActorCommands; #endif diff --git a/stepmania/src/Makefile.am b/stepmania/src/Makefile.am index 3dd5eeb1d0..f6e924ed45 100644 --- a/stepmania/src/Makefile.am +++ b/stepmania/src/Makefile.am @@ -258,7 +258,8 @@ RageSurface_Load_XPM.cpp RageSurface_Load_XPM.h RageTexture.cpp RageTexture.h \ RageSurface_Save_BMP.cpp RageSurface_Save_BMP.h \ RageTextureID.cpp RageTextureID.h RageTextureManager.cpp RageTextureManager.h RageThreads.cpp RageThreads.h \ RageTimer.cpp RageTimer.h RageTypes.h RageUtil.cpp RageUtil.h RageUtil_CharConversions.cpp RageUtil_CharConversions.h \ -RageUtil_BackgroundLoader.cpp RageUtil_BackgroundLoader.h RageUtil_FileDB.cpp RageUtil_FileDB.h RageUtil_CircularBuffer.h +RageUtil_BackgroundLoader.cpp RageUtil_BackgroundLoader.h RageUtil_FileDB.cpp RageUtil_FileDB.h RageUtil_CircularBuffer.h \ +RageUtil_AutoPtr.h Actors = \ Actor.cpp Actor.h ActorCollision.h ActorFrame.cpp ActorFrame.h \ diff --git a/stepmania/src/RageUtil_AutoPtr.h b/stepmania/src/RageUtil_AutoPtr.h new file mode 100644 index 0000000000..c018de1868 --- /dev/null +++ b/stepmania/src/RageUtil_AutoPtr.h @@ -0,0 +1,122 @@ +#ifndef RAGE_UTIL_AUTO_PTR_H +#define RAGE_UTIL_AUTO_PTR_H + +/* + * This is a simple copy-on-write refcounted smart pointer. Once constructed, all read-only + * access to the object is made without extra copying. If you need read-write access, you + * can get a pointer with Get(), which will cause the object to deep-copy. (Don't free + * the resulting pointer.) + * + * Note that there are no non-const operator* or operator-> overloads, because that would + * cause all const access by code with non-const permissions to deep-copy. For example, + * + * AutoPtrCopyOnWrite a( new int(1) ); + * AutoPtrCopyOnWrite b( a ); + * printf( "%i\n", *a ); + * + * If we have a non-const operator*, this *a will use it (even though it only needs const + * access), and will copy the underlying object wastefully. g++ std::string has this behavior, + * which is why it's important to qualify strings as "const" when const access is desired, + * but that's brittle, so let's make all potential deep-copying explicit. + */ + +template +class AutoPtrCopyOnWrite +{ +public: + /* This constructor only exists to make us work with STL containers. */ + inline AutoPtrCopyOnWrite() + { + m_pPtr = NULL; + m_iRefCount = new int(1); + } + + explicit inline AutoPtrCopyOnWrite( T *p ) + { + m_pPtr = p; + m_iRefCount = new int(1); + } + + inline AutoPtrCopyOnWrite( const AutoPtrCopyOnWrite &rhs ) + { + m_pPtr = rhs.m_pPtr; + m_iRefCount = rhs.m_iRefCount; + ++(*m_iRefCount); + } + + void Swap( AutoPtrCopyOnWrite &rhs ) + { + swap( m_pPtr, rhs.m_pPtr ); + swap( m_iRefCount, rhs.m_iRefCount ); + } + + inline AutoPtrCopyOnWrite &operator=( const AutoPtrCopyOnWrite &rhs ) + { + AutoPtrCopyOnWrite obj( rhs ); + this->Swap( obj ); + return *this; + } + + ~AutoPtrCopyOnWrite() + { + --(*m_iRefCount); + if( *m_iRefCount == 0 ) + { + delete m_pPtr; + delete m_iRefCount; + } + } + + /* Get a non-const pointer. This will deep-copy the object if necessary. */ + T *Get() + { + if( *m_iRefCount > 1 ) + { + --*m_iRefCount; + m_pPtr = new T(*m_pPtr); + m_iRefCount = new int(1); + } + + return m_pPtr; + } + + const T &operator *() const { return *m_pPtr; } + const T *operator ->() const { return m_pPtr; } + +private: + T *m_pPtr; + int *m_iRefCount; +}; + +template +inline void swap( AutoPtrCopyOnWrite &a, AutoPtrCopyOnWrite &b ) +{ + a.Swap(b); +} + +#endif + +/* + * (c) 2005 Glenn Maynard + * 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/StepMania.dsp b/stepmania/src/StepMania.dsp index 28c758b2d4..78b7a9c2ab 100644 --- a/stepmania/src/StepMania.dsp +++ b/stepmania/src/StepMania.dsp @@ -62,7 +62,7 @@ IntDir=.\../Debug6 TargetDir=\temp\stepmania\Program TargetName=StepMania-debug SOURCE="$(InputPath)" -PreLink_Cmds=archutils\Win32\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PreLink_Cmds=archutils\Win32\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ PostBuild_Cmds=archutils\Win32\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi # End Special Build Tool @@ -99,7 +99,7 @@ IntDir=.\../Release6 TargetDir=\temp\stepmania\Program TargetName=StepMania SOURCE="$(InputPath)" -PreLink_Cmds=archutils\Win32\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PreLink_Cmds=archutils\Win32\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ PostBuild_Cmds=archutils\Win32\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi # End Special Build Tool @@ -604,6 +604,10 @@ SOURCE=.\RageUtil.h # End Source File # Begin Source File +SOURCE=.\RageUtil_AutoPtr.h +# End Source File +# Begin Source File + SOURCE=.\RageUtil_BackgroundLoader.cpp # End Source File # Begin Source File diff --git a/stepmania/src/StepMania.vcproj b/stepmania/src/StepMania.vcproj index 8847b0aaf0..409ba732cf 100644 --- a/stepmania/src/StepMania.vcproj +++ b/stepmania/src/StepMania.vcproj @@ -2138,6 +2138,9 @@ cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\ + +