I am attempting to write a "Phoenix Singleton" using the book "Modern C++
Design" by Alexandrescu
I do not understand his use of...
#ifndef ATEXIT_FIXED
std::atexit(Kil l);
#endif
....in the source below. I understand the problem, but not how a preprocessor
directive will fix it. He says the standard is unclear about the situation
where one call to register with std::atexit is the result of is made as an
effect of another std::atexit registration. Can anyone be more specific on
how to fix the problem?
Source (forgive the indenting problems as a result of editor
incompatibiliti es):
// .h file
#ifndef SINGLETON_PHOEN IX
#define SINGLETON_PHOEN IX
#include "BaseException. h"
namespace cpisz_common_li b
{
//----------------------------------------------------------------------------------------------------------------------
/**
* Singleton_Pheon ix
*
* A singleton pattern that guarentees an instance will always be available.
*
*/
class Singleton_Phoen ix
{
public:
/**
* Retreives a reference to this singleton
*/
static Singleton_Phoen ix & GetInstance();
private:
static void Create();
static void Kill();
static void OnDeadReference ();
Singleton_Phoen ix();
Singleton_Phoen ix(const Singleton_Phoen ix &);
virtual ~Singleton_Phoe nix();
Singleton_Phoen ix & operator = (const Singleton_Phoen ix &);
static Singleton_Phoen ix * m_instance; // Pointer to the instance of this
object
static bool m_destroyed; // Flag that indicates the instance has been
destroyed
};
} // namespace cpisz_common_li b
#endif
// .cpp file
#include "Singleton_Phoe nix.h"
#include <cstdlib>
namespace cpisz_common_li b
{
//----------------------------------------------------------------------------------------------------------------------
Singleton_Phoen ix * Singleton_Phoen ix::m_instance = 0;
bool Singleton_Phoen ix::m_destroyed = false;
//----------------------------------------------------------------------------------------------------------------------
Singleton_Phoen ix & Singleton_Phoen ix::GetInstance ()
{
// Check if the object is instantiated
if( !m_instance )
{
// Check for dead reference
if( m_destroyed )
{
// Create a new instance, replacing the old destroyed instance
OnDeadReference ();
}
else
{
// Create the first instance
Create();
}
}
return *m_instance;
}
//----------------------------------------------------------------------------------------------------------------------
void Singleton_Phoen ix::Create()
{
static Singleton_Phoen ix instance;
m_instance = &instance;
}
//----------------------------------------------------------------------------------------------------------------------
void Singleton_Phoen ix::Kill()
{
// Set the instance pointer to NULL and destroyed flag to true;
m_instance->~Singleton_Pho enix();
}
//----------------------------------------------------------------------------------------------------------------------
void Singleton_Phoen ix::OnDeadRefer ence()
{
// Get the shell of the old reference to the instance
Create();
// Create a new instance at that same address
// Using the "placement new operator"
new(m_instance) Singleton_Phoen ix;
// Queue this new objects destruction
#ifndef ATEXIT_FIXED
std::atexit(Kil l);
#endif
// Reset the destoryed flag
m_destroyed = false;
}
//----------------------------------------------------------------------------------------------------------------------
Singleton_Phoen ix::~Singleton_ Phoenix()
{
m_instance = 0;
m_destroyed = true;
}
} // namespace cpisz_common_li b