C
Christopher Pisz
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(Kill);
#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
incompatibilities):
// .h file
#ifndef SINGLETON_PHOENIX
#define SINGLETON_PHOENIX
#include "BaseException.h"
namespace cpisz_common_lib
{
//----------------------------------------------------------------------------------------------------------------------
/**
* Singleton_Pheonix
*
* A singleton pattern that guarentees an instance will always be available.
*
*/
class Singleton_Phoenix
{
public:
/**
* Retreives a reference to this singleton
*/
static Singleton_Phoenix & GetInstance();
private:
static void Create();
static void Kill();
static void OnDeadReference();
Singleton_Phoenix();
Singleton_Phoenix(const Singleton_Phoenix &);
virtual ~Singleton_Phoenix();
Singleton_Phoenix & operator = (const Singleton_Phoenix &);
static Singleton_Phoenix * m_instance; // Pointer to the instance of this
object
static bool m_destroyed; // Flag that indicates the instance has been
destroyed
};
} // namespace cpisz_common_lib
#endif
// .cpp file
#include "Singleton_Phoenix.h"
#include <cstdlib>
namespace cpisz_common_lib
{
//----------------------------------------------------------------------------------------------------------------------
Singleton_Phoenix * Singleton_Phoenix::m_instance = 0;
bool Singleton_Phoenix::m_destroyed = false;
//----------------------------------------------------------------------------------------------------------------------
Singleton_Phoenix & Singleton_Phoenix::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_Phoenix::Create()
{
static Singleton_Phoenix instance;
m_instance = &instance;
}
//----------------------------------------------------------------------------------------------------------------------
void Singleton_Phoenix::Kill()
{
// Set the instance pointer to NULL and destroyed flag to true;
m_instance->~Singleton_Phoenix();
}
//----------------------------------------------------------------------------------------------------------------------
void Singleton_Phoenix::OnDeadReference()
{
// 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_Phoenix;
// Queue this new objects destruction
#ifndef ATEXIT_FIXED
std::atexit(Kill);
#endif
// Reset the destoryed flag
m_destroyed = false;
}
//----------------------------------------------------------------------------------------------------------------------
Singleton_Phoenix::~Singleton_Phoenix()
{
m_instance = 0;
m_destroyed = true;
}
} // namespace cpisz_common_lib
Design" by Alexandrescu
I do not understand his use of...
#ifndef ATEXIT_FIXED
std::atexit(Kill);
#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
incompatibilities):
// .h file
#ifndef SINGLETON_PHOENIX
#define SINGLETON_PHOENIX
#include "BaseException.h"
namespace cpisz_common_lib
{
//----------------------------------------------------------------------------------------------------------------------
/**
* Singleton_Pheonix
*
* A singleton pattern that guarentees an instance will always be available.
*
*/
class Singleton_Phoenix
{
public:
/**
* Retreives a reference to this singleton
*/
static Singleton_Phoenix & GetInstance();
private:
static void Create();
static void Kill();
static void OnDeadReference();
Singleton_Phoenix();
Singleton_Phoenix(const Singleton_Phoenix &);
virtual ~Singleton_Phoenix();
Singleton_Phoenix & operator = (const Singleton_Phoenix &);
static Singleton_Phoenix * m_instance; // Pointer to the instance of this
object
static bool m_destroyed; // Flag that indicates the instance has been
destroyed
};
} // namespace cpisz_common_lib
#endif
// .cpp file
#include "Singleton_Phoenix.h"
#include <cstdlib>
namespace cpisz_common_lib
{
//----------------------------------------------------------------------------------------------------------------------
Singleton_Phoenix * Singleton_Phoenix::m_instance = 0;
bool Singleton_Phoenix::m_destroyed = false;
//----------------------------------------------------------------------------------------------------------------------
Singleton_Phoenix & Singleton_Phoenix::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_Phoenix::Create()
{
static Singleton_Phoenix instance;
m_instance = &instance;
}
//----------------------------------------------------------------------------------------------------------------------
void Singleton_Phoenix::Kill()
{
// Set the instance pointer to NULL and destroyed flag to true;
m_instance->~Singleton_Phoenix();
}
//----------------------------------------------------------------------------------------------------------------------
void Singleton_Phoenix::OnDeadReference()
{
// 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_Phoenix;
// Queue this new objects destruction
#ifndef ATEXIT_FIXED
std::atexit(Kill);
#endif
// Reset the destoryed flag
m_destroyed = false;
}
//----------------------------------------------------------------------------------------------------------------------
Singleton_Phoenix::~Singleton_Phoenix()
{
m_instance = 0;
m_destroyed = true;
}
} // namespace cpisz_common_lib