Original Post
I am starting to work on thread-safety in my program, and I would like to have someone check over my work to make sure I am understanding it right. I am compiling on MSVC 2005 (and will cross-compile on GCC, so I want to make sure the code works). I use an object called nullptr instead of 0, except in InterlockedExchangePointer it gives a compiler error because that takes a LONG. Could someone also clarify the thread-safety of atexit() in this case? Is it acceptable to delete InstancePtr from another thread than the one that allocated it? I am going to be focusing on VC8 and GCC (MinGW) 3.4.2, although I intend to port it to another platform.
template < typename T >
class PhoenixSingletonHolder {
public:
typename typedef T ObjectType;
private:
static void MakeInstance() {
#ifdef PSYKR_WIN32
// create a new object, and slip it in the back
T* NewInstancePtr = new T();
// if the exchange failed, we already have an instance
if( nullptr != InterlockedCompareExchangePointer( &InstancePtr, NewInstancePtr, nullptr ) )
delete NewInstancePtr;
// otherwise, we created a new object so schedule its destruction
else std::atexit( &DestroySingleton );
#else
T* NewInstancePtr = new T();
if( nullptr != InstancePtr )
delete NewInstancePtr;
else { // if( nullptr == InstancePtr )
InstancePtr = NewInstancePtr;
std::atexit( &DestroySingleton );
}
#endif //!PSYKR_WIN32
}
static void DestroySingleton() {
#ifdef PSYKR_WIN32
// this will either delete InstancePtr, or a nullptr (which is okay)
delete( InterlockedExchangePointer( InstancePtr, 0 ) );
#else
delete InstancePtr;
InstancePtr = nullptr;
#endif //!PSYKR_WIN32
}
public:
// this is what's really returned by Singleton<T>::Instance()
static T& Instance() {
if( nullptr == InstancePtr )
MakeInstance();
return *InstancePtr;
}
private:
static T* volatile InstancePtr;
};