Removed trailing whitespaces.
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@1085 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
2bc8950456
commit
6cb58ee8cc
1 changed files with 109 additions and 107 deletions
|
@ -2,14 +2,14 @@
|
||||||
// The Loki Library
|
// The Loki Library
|
||||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
// This code accompanies the book:
|
// This code accompanies the book:
|
||||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
// Permission to use, copy, modify, distribute and sell this software for any
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
// purpose is hereby granted without fee, provided that the above copyright
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
// notice appear in all copies and that both that copyright notice and this
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
// permission notice appear in supporting documentation.
|
// permission notice appear in supporting documentation.
|
||||||
// The author or Addison-Wesley Longman make no representations about the
|
// The author or Addison-Wesley Longman make no representations about the
|
||||||
// suitability of this software for any purpose. It is provided "as is"
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
// without express or implied warranty.
|
// without express or implied warranty.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
#ifndef LOKI_SINGLETON_INC_
|
#ifndef LOKI_SINGLETON_INC_
|
||||||
|
@ -30,9 +30,9 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define LOKI_C_CALLING_CONVENTION_QUALIFIER __cdecl
|
#define LOKI_C_CALLING_CONVENTION_QUALIFIER __cdecl
|
||||||
#else
|
#else
|
||||||
#define LOKI_C_CALLING_CONVENTION_QUALIFIER
|
#define LOKI_C_CALLING_CONVENTION_QUALIFIER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// \defgroup SingletonGroup Singleton
|
/// \defgroup SingletonGroup Singleton
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
/// \ingroup SingletonGroup
|
/// \ingroup SingletonGroup
|
||||||
/// The lifetimes of the singleton.
|
/// The lifetimes of the singleton.
|
||||||
/// \par Special lifetime for SmallObjects
|
/// \par Special lifetime for SmallObjects
|
||||||
/// When the holded object is a Small(Value)Object or the holded object
|
/// When the holded object is a Small(Value)Object or the holded object
|
||||||
/// uses objects which are or inherit from Small(Value)Object
|
/// uses objects which are or inherit from Small(Value)Object
|
||||||
/// then you can't use the default lifetime: you must use the lifetime
|
/// then you can't use the default lifetime: you must use the lifetime
|
||||||
/// \code Loki::LongevityLifetime::DieAsSmallObjectChild \endcode
|
/// \code Loki::LongevityLifetime::DieAsSmallObjectChild \endcode
|
||||||
|
@ -58,14 +58,14 @@ namespace Loki
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifndef LOKI_MAKE_DLL
|
#ifndef LOKI_MAKE_DLL
|
||||||
void LOKI_C_CALLING_CONVENTION_QUALIFIER AtExitFn(); // declaration needed below
|
void LOKI_C_CALLING_CONVENTION_QUALIFIER AtExitFn(); // declaration needed below
|
||||||
#else
|
#else
|
||||||
void LOKI_EXPORT AtExitFn();
|
void LOKI_EXPORT AtExitFn();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class LifetimeTracker;
|
class LifetimeTracker;
|
||||||
|
|
||||||
#define LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
|
#define LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
|
||||||
#ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
|
#ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
|
||||||
|
|
||||||
// Helper data
|
// Helper data
|
||||||
|
@ -87,23 +87,23 @@ namespace Loki
|
||||||
class LifetimeTracker
|
class LifetimeTracker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LifetimeTracker(unsigned int x) : longevity_(x)
|
LifetimeTracker(unsigned int x) : longevity_(x)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual ~LifetimeTracker() = 0;
|
virtual ~LifetimeTracker() = 0;
|
||||||
|
|
||||||
static bool Compare(const LifetimeTracker* lhs,
|
static bool Compare(const LifetimeTracker* lhs,
|
||||||
const LifetimeTracker* rhs)
|
const LifetimeTracker* rhs)
|
||||||
{
|
{
|
||||||
return lhs->longevity_ > rhs->longevity_;
|
return lhs->longevity_ > rhs->longevity_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int longevity_;
|
unsigned int longevity_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Definition required
|
// Definition required
|
||||||
inline LifetimeTracker::~LifetimeTracker() {}
|
inline LifetimeTracker::~LifetimeTracker() {}
|
||||||
|
|
||||||
// Helper destroyer function
|
// Helper destroyer function
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -124,11 +124,13 @@ namespace Loki
|
||||||
, pTracked_(p)
|
, pTracked_(p)
|
||||||
, destroyer_(d)
|
, destroyer_(d)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~ConcreteLifetimeTracker()
|
~ConcreteLifetimeTracker()
|
||||||
{ destroyer_(pTracked_); }
|
{ destroyer_(pTracked_); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Copy constructor is not implemented.
|
||||||
|
ConcreteLifetimeTracker( const ConcreteLifetimeTracker & );
|
||||||
T* pTracked_;
|
T* pTracked_;
|
||||||
Destroyer destroyer_;
|
Destroyer destroyer_;
|
||||||
};
|
};
|
||||||
|
@ -137,8 +139,8 @@ namespace Loki
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \ingroup LifetimeGroup
|
/// \ingroup LifetimeGroup
|
||||||
///
|
///
|
||||||
/// Assigns an object a longevity; ensures ordered destructions of objects
|
/// Assigns an object a longevity; ensures ordered destructions of objects
|
||||||
/// registered thusly during the exit sequence of the application
|
/// registered thusly during the exit sequence of the application
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -155,58 +157,58 @@ namespace Loki
|
||||||
pTrackerArray = new TrackerArray;
|
pTrackerArray = new TrackerArray;
|
||||||
|
|
||||||
// automatically delete the ConcreteLifetimeTracker object when a exception is thrown
|
// automatically delete the ConcreteLifetimeTracker object when a exception is thrown
|
||||||
std::auto_ptr<LifetimeTracker>
|
std::auto_ptr<LifetimeTracker>
|
||||||
p( new ConcreteLifetimeTracker<T, Destroyer>(pDynObject, longevity, d) );
|
p( new ConcreteLifetimeTracker<T, Destroyer>(pDynObject, longevity, d) );
|
||||||
|
|
||||||
// Find correct position
|
// Find correct position
|
||||||
TrackerArray::iterator pos = std::upper_bound(
|
TrackerArray::iterator pos = std::upper_bound(
|
||||||
pTrackerArray->begin(),
|
pTrackerArray->begin(),
|
||||||
pTrackerArray->end(),
|
pTrackerArray->end(),
|
||||||
p.get(),
|
p.get(),
|
||||||
LifetimeTracker::Compare);
|
LifetimeTracker::Compare);
|
||||||
|
|
||||||
// Insert the pointer to the ConcreteLifetimeTracker object into the queue
|
// Insert the pointer to the ConcreteLifetimeTracker object into the queue
|
||||||
pTrackerArray->insert(pos, p.get());
|
pTrackerArray->insert(pos, p.get());
|
||||||
|
|
||||||
// nothing has thrown: don't delete the ConcreteLifetimeTracker object
|
// nothing has thrown: don't delete the ConcreteLifetimeTracker object
|
||||||
p.release();
|
p.release();
|
||||||
|
|
||||||
// Register a call to AtExitFn
|
// Register a call to AtExitFn
|
||||||
std::atexit(Private::AtExitFn);
|
std::atexit(Private::AtExitFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
template <typename T, typename Destroyer>
|
template <typename T, typename Destroyer>
|
||||||
void SetLongevity(T* pDynObject, unsigned int longevity,
|
void SetLongevity(T* pDynObject, unsigned int longevity,
|
||||||
Destroyer d)
|
Destroyer d)
|
||||||
{
|
{
|
||||||
using namespace Private;
|
using namespace Private;
|
||||||
|
|
||||||
TrackerArray pNewArray = static_cast<TrackerArray>(
|
TrackerArray pNewArray = static_cast<TrackerArray>(
|
||||||
std::realloc(pTrackerArray,
|
std::realloc(pTrackerArray,
|
||||||
sizeof(*pTrackerArray) * (elements + 1)));
|
sizeof(*pTrackerArray) * (elements + 1)));
|
||||||
if (!pNewArray) throw std::bad_alloc();
|
if (!pNewArray) throw std::bad_alloc();
|
||||||
|
|
||||||
// Delayed assignment for exception safety
|
// Delayed assignment for exception safety
|
||||||
pTrackerArray = pNewArray;
|
pTrackerArray = pNewArray;
|
||||||
|
|
||||||
LifetimeTracker* p = new ConcreteLifetimeTracker<T, Destroyer>(
|
LifetimeTracker* p = new ConcreteLifetimeTracker<T, Destroyer>(
|
||||||
pDynObject, longevity, d);
|
pDynObject, longevity, d);
|
||||||
|
|
||||||
// Insert a pointer to the object into the queue
|
// Insert a pointer to the object into the queue
|
||||||
TrackerArray pos = std::upper_bound(
|
TrackerArray pos = std::upper_bound(
|
||||||
pTrackerArray,
|
pTrackerArray,
|
||||||
pTrackerArray + elements,
|
pTrackerArray + elements,
|
||||||
p,
|
p,
|
||||||
LifetimeTracker::Compare);
|
LifetimeTracker::Compare);
|
||||||
std::copy_backward(
|
std::copy_backward(
|
||||||
pos,
|
pos,
|
||||||
pTrackerArray + elements,
|
pTrackerArray + elements,
|
||||||
pTrackerArray + elements + 1);
|
pTrackerArray + elements + 1);
|
||||||
*pos = p;
|
*pos = p;
|
||||||
++elements;
|
++elements;
|
||||||
|
|
||||||
// Register a call to AtExitFn
|
// Register a call to AtExitFn
|
||||||
std::atexit(Private::AtExitFn);
|
std::atexit(Private::AtExitFn);
|
||||||
}
|
}
|
||||||
|
@ -221,21 +223,21 @@ namespace Loki
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \struct CreateUsingNew
|
/// \struct CreateUsingNew
|
||||||
///
|
///
|
||||||
/// \ingroup CreationGroup
|
/// \ingroup CreationGroup
|
||||||
/// Implementation of the CreationPolicy used by SingletonHolder
|
/// Implementation of the CreationPolicy used by SingletonHolder
|
||||||
/// Creates objects using a straight call to the new operator
|
/// Creates objects using a straight call to the new operator
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <class T> struct CreateUsingNew
|
template <class T> struct CreateUsingNew
|
||||||
{
|
{
|
||||||
static T* Create()
|
static T* Create()
|
||||||
{ return new T; }
|
{ return new T; }
|
||||||
|
|
||||||
static void Destroy(T* p)
|
static void Destroy(T* p)
|
||||||
{ delete p; }
|
{ delete p; }
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \struct CreateUsing
|
/// \struct CreateUsing
|
||||||
///
|
///
|
||||||
|
@ -265,13 +267,13 @@ namespace Loki
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \struct CreateUsingMalloc
|
/// \struct CreateUsingMalloc
|
||||||
///
|
///
|
||||||
/// \ingroup CreationGroup
|
/// \ingroup CreationGroup
|
||||||
/// Implementation of the CreationPolicy used by SingletonHolder
|
/// Implementation of the CreationPolicy used by SingletonHolder
|
||||||
/// Creates objects using a call to std::malloc, followed by a call to the
|
/// Creates objects using a call to std::malloc, followed by a call to the
|
||||||
/// placement new operator
|
/// placement new operator
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <class T> struct CreateUsingMalloc
|
template <class T> struct CreateUsingMalloc
|
||||||
|
@ -282,14 +284,14 @@ namespace Loki
|
||||||
if (!p) return 0;
|
if (!p) return 0;
|
||||||
return new(p) T;
|
return new(p) T;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Destroy(T* p)
|
static void Destroy(T* p)
|
||||||
{
|
{
|
||||||
p->~T();
|
p->~T();
|
||||||
std::free(p);
|
std::free(p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \struct CreateStatic
|
/// \struct CreateStatic
|
||||||
|
@ -297,15 +299,15 @@ namespace Loki
|
||||||
/// \ingroup CreationGroup
|
/// \ingroup CreationGroup
|
||||||
/// Implementation of the CreationPolicy used by SingletonHolder
|
/// Implementation of the CreationPolicy used by SingletonHolder
|
||||||
/// Creates an object in static memory
|
/// Creates an object in static memory
|
||||||
/// Implementation is slightly nonportable because it uses the MaxAlign trick
|
/// Implementation is slightly nonportable because it uses the MaxAlign trick
|
||||||
/// (an union of all types to ensure proper memory alignment). This trick is
|
/// (an union of all types to ensure proper memory alignment). This trick is
|
||||||
/// nonportable in theory but highly portable in practice.
|
/// nonportable in theory but highly portable in practice.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <class T> struct CreateStatic
|
template <class T> struct CreateStatic
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning( push )
|
#pragma warning( push )
|
||||||
#pragma warning( disable : 4121 )
|
#pragma warning( disable : 4121 )
|
||||||
// alignment of a member was sensitive to packing
|
// alignment of a member was sensitive to packing
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
@ -323,17 +325,17 @@ namespace Loki
|
||||||
int Test::* pMember_;
|
int Test::* pMember_;
|
||||||
int (Test::*pMemberFn_)(int);
|
int (Test::*pMemberFn_)(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning( pop )
|
#pragma warning( pop )
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
static T* Create()
|
static T* Create()
|
||||||
{
|
{
|
||||||
static MaxAlign staticMemory_;
|
static MaxAlign staticMemory_;
|
||||||
return new(&staticMemory_) T;
|
return new(&staticMemory_) T;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Destroy(T* p)
|
static void Destroy(T* p)
|
||||||
{
|
{
|
||||||
p->~T();
|
p->~T();
|
||||||
|
@ -353,7 +355,7 @@ namespace Loki
|
||||||
{
|
{
|
||||||
static void ScheduleDestruction(T*, atexit_pfn_t pFun)
|
static void ScheduleDestruction(T*, atexit_pfn_t pFun)
|
||||||
{ std::atexit(pFun); }
|
{ std::atexit(pFun); }
|
||||||
|
|
||||||
static void OnDeadReference()
|
static void OnDeadReference()
|
||||||
{ throw std::logic_error("Dead Reference Detected"); }
|
{ throw std::logic_error("Dead Reference Detected"); }
|
||||||
};
|
};
|
||||||
|
@ -363,7 +365,7 @@ namespace Loki
|
||||||
///
|
///
|
||||||
/// \ingroup LifetimeGroup
|
/// \ingroup LifetimeGroup
|
||||||
/// Implementation of the LifetimePolicy used by SingletonHolder
|
/// Implementation of the LifetimePolicy used by SingletonHolder
|
||||||
/// Schedules an object's destruction as per C++ rules, and it allows object
|
/// Schedules an object's destruction as per C++ rules, and it allows object
|
||||||
/// recreation by not throwing an exception from OnDeadReference
|
/// recreation by not throwing an exception from OnDeadReference
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -377,20 +379,20 @@ namespace Loki
|
||||||
#endif
|
#endif
|
||||||
std::atexit(pFun);
|
std::atexit(pFun);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnDeadReference()
|
static void OnDeadReference()
|
||||||
{
|
{
|
||||||
#ifndef ATEXIT_FIXED
|
#ifndef ATEXIT_FIXED
|
||||||
destroyedOnce_ = true;
|
destroyedOnce_ = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifndef ATEXIT_FIXED
|
#ifndef ATEXIT_FIXED
|
||||||
static bool destroyedOnce_;
|
static bool destroyedOnce_;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef ATEXIT_FIXED
|
#ifndef ATEXIT_FIXED
|
||||||
template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false;
|
template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -402,13 +404,13 @@ namespace Loki
|
||||||
///
|
///
|
||||||
/// \ingroup LifetimeGroup
|
/// \ingroup LifetimeGroup
|
||||||
///
|
///
|
||||||
/// A DeletableSingleton allows the instantiated singleton to be
|
/// A DeletableSingleton allows the instantiated singleton to be
|
||||||
/// destroyed at any time. The singleton can be reinstantiated at
|
/// destroyed at any time. The singleton can be reinstantiated at
|
||||||
/// any time, even during program termination.
|
/// any time, even during program termination.
|
||||||
/// If the singleton exists when the program terminates, it will
|
/// If the singleton exists when the program terminates, it will
|
||||||
/// be automatically deleted.
|
/// be automatically deleted.
|
||||||
///
|
///
|
||||||
/// \par Usage:
|
/// \par Usage:
|
||||||
/// The singleton can be deleted manually:
|
/// The singleton can be deleted manually:
|
||||||
///
|
///
|
||||||
/// DeletableSingleton<MyClass>::GracefulDelete();
|
/// DeletableSingleton<MyClass>::GracefulDelete();
|
||||||
|
@ -430,9 +432,9 @@ namespace Loki
|
||||||
needCallback = false;
|
needCallback = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnDeadReference()
|
static void OnDeadReference()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
/// delete singleton object manually
|
/// delete singleton object manually
|
||||||
static void GracefulDelete()
|
static void GracefulDelete()
|
||||||
|
@ -442,12 +444,12 @@ namespace Loki
|
||||||
isDead = true;
|
isDead = true;
|
||||||
deleter();
|
deleter();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static atexit_pfn_t deleter;
|
static atexit_pfn_t deleter;
|
||||||
static bool isDead;
|
static bool isDead;
|
||||||
static bool needCallback;
|
static bool needCallback;
|
||||||
|
|
||||||
static void atexitCallback()
|
static void atexitCallback()
|
||||||
{
|
{
|
||||||
#ifdef ATEXIT_FIXED
|
#ifdef ATEXIT_FIXED
|
||||||
|
@ -458,13 +460,13 @@ namespace Loki
|
||||||
GracefulDelete();
|
GracefulDelete();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
atexit_pfn_t DeletableSingleton<T>::deleter = 0;
|
atexit_pfn_t DeletableSingleton<T>::deleter = 0;
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
bool DeletableSingleton<T>::isDead = true;
|
bool DeletableSingleton<T>::isDead = true;
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
bool DeletableSingleton<T>::needCallback = true;
|
bool DeletableSingleton<T>::needCallback = true;
|
||||||
|
|
||||||
|
@ -501,7 +503,7 @@ namespace Loki
|
||||||
Private::Adapter<T> adapter = { pFun };
|
Private::Adapter<T> adapter = { pFun };
|
||||||
SetLongevity(pObj, GetLongevity(pObj), adapter);
|
SetLongevity(pObj, GetLongevity(pObj), adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnDeadReference()
|
static void OnDeadReference()
|
||||||
{ throw std::logic_error("Dead Reference Detected"); }
|
{ throw std::logic_error("Dead Reference Detected"); }
|
||||||
};
|
};
|
||||||
|
@ -518,11 +520,11 @@ namespace Loki
|
||||||
{
|
{
|
||||||
static void ScheduleDestruction(T*, atexit_pfn_t)
|
static void ScheduleDestruction(T*, atexit_pfn_t)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
static void OnDeadReference()
|
static void OnDeadReference()
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \defgroup LongevityLifetimeGroup LongevityLifetime
|
/// \defgroup LongevityLifetimeGroup LongevityLifetime
|
||||||
|
@ -537,7 +539,7 @@ namespace Loki
|
||||||
namespace LongevityLifetime
|
namespace LongevityLifetime
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \struct SingletonFixedLongevity
|
/// \struct SingletonFixedLongevity
|
||||||
///
|
///
|
||||||
/// \ingroup LongevityLifetimeGroup
|
/// \ingroup LongevityLifetimeGroup
|
||||||
/// Add your own lifetimes into the namespace 'LongevityLifetime'
|
/// Add your own lifetimes into the namespace 'LongevityLifetime'
|
||||||
|
@ -551,13 +553,13 @@ namespace Loki
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~SingletonFixedLongevity() {}
|
virtual ~SingletonFixedLongevity() {}
|
||||||
|
|
||||||
static void ScheduleDestruction(T* pObj, atexit_pfn_t pFun)
|
static void ScheduleDestruction(T* pObj, atexit_pfn_t pFun)
|
||||||
{
|
{
|
||||||
Private::Adapter<T> adapter = { pFun };
|
Private::Adapter<T> adapter = { pFun };
|
||||||
SetLongevity(pObj, Longevity , adapter);
|
SetLongevity(pObj, Longevity , adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnDeadReference()
|
static void OnDeadReference()
|
||||||
{ throw std::logic_error("Dead Reference Detected"); }
|
{ throw std::logic_error("Dead Reference Detected"); }
|
||||||
};
|
};
|
||||||
|
@ -578,11 +580,11 @@ namespace Loki
|
||||||
|
|
||||||
/// \struct DieFirst
|
/// \struct DieFirst
|
||||||
/// \ingroup LongevityLifetimeGroup
|
/// \ingroup LongevityLifetimeGroup
|
||||||
/// \brief Shortest possible SingletonWithLongevity lifetime: 0
|
/// \brief Shortest possible SingletonWithLongevity lifetime: 0
|
||||||
template <class T>
|
template <class T>
|
||||||
struct DieFirst : SingletonFixedLongevity<0,T>
|
struct DieFirst : SingletonFixedLongevity<0,T>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
}//namespace LongevityLifetime
|
}//namespace LongevityLifetime
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -590,12 +592,12 @@ namespace Loki
|
||||||
///
|
///
|
||||||
/// \ingroup LifetimeGroup
|
/// \ingroup LifetimeGroup
|
||||||
///
|
///
|
||||||
/// Lifetime policyfor the SingletonHolder tempalte.
|
/// Lifetime policyfor the SingletonHolder tempalte.
|
||||||
/// Followers will die after the master dies Followers will not die, if
|
/// Followers will die after the master dies Followers will not die, if
|
||||||
/// - master never dies (NoDestroy policy)
|
/// - master never dies (NoDestroy policy)
|
||||||
/// - master never created
|
/// - master never created
|
||||||
/// - master dies not in the function registered with atexit
|
/// - master dies not in the function registered with atexit
|
||||||
/// - master dies not by a call of a the atexit registerd function (DeletableSingleton::GracefulDelete)
|
/// - master dies not by a call of a the atexit registerd function (DeletableSingleton::GracefulDelete)
|
||||||
///
|
///
|
||||||
/// \par Usage:
|
/// \par Usage:
|
||||||
///
|
///
|
||||||
|
@ -611,7 +613,7 @@ namespace Loki
|
||||||
typedef std::vector<atexit_pfn_t> Container;
|
typedef std::vector<atexit_pfn_t> Container;
|
||||||
typedef typename Container::iterator iterator;
|
typedef typename Container::iterator iterator;
|
||||||
static Container* followers_;
|
static Container* followers_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void Init()
|
static void Init()
|
||||||
{
|
{
|
||||||
|
@ -633,7 +635,7 @@ namespace Loki
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
for(iterator it = followers_->begin();it != followers_->end();++it)
|
for(iterator it = followers_->begin();it != followers_->end();++it)
|
||||||
(*it)();
|
(*it)();
|
||||||
delete followers_;
|
delete followers_;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -641,7 +643,7 @@ namespace Loki
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// \struct With
|
/// \struct With
|
||||||
/// Template for the master
|
/// Template for the master
|
||||||
/// \param Lifetime Lifetime policy for the master
|
/// \param Lifetime Lifetime policy for the master
|
||||||
template<template <class> class Lifetime>
|
template<template <class> class Lifetime>
|
||||||
struct With
|
struct With
|
||||||
|
@ -656,7 +658,7 @@ namespace Loki
|
||||||
Followers<Master>::Init();
|
Followers<Master>::Init();
|
||||||
Lifetime<Master>::ScheduleDestruction(pObj, pFun);
|
Lifetime<Master>::ScheduleDestruction(pObj, pFun);
|
||||||
|
|
||||||
// use same policy for the followers and force a new
|
// use same policy for the followers and force a new
|
||||||
// template instantiation, this adds a additional atexit entry
|
// template instantiation, this adds a additional atexit entry
|
||||||
// does not work with SetLonlevity, but there you can control
|
// does not work with SetLonlevity, but there you can control
|
||||||
// the lifetime with the GetLongevity function.
|
// the lifetime with the GetLongevity function.
|
||||||
|
@ -664,8 +666,8 @@ namespace Loki
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnDeadReference()
|
static void OnDeadReference()
|
||||||
{
|
{
|
||||||
throw std::logic_error("Dead Reference Detected");
|
throw std::logic_error("Dead Reference Detected");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -677,7 +679,7 @@ namespace Loki
|
||||||
struct AfterMaster
|
struct AfterMaster
|
||||||
{
|
{
|
||||||
/// \struct IsDestroyed
|
/// \struct IsDestroyed
|
||||||
/// Policy for followers
|
/// Policy for followers
|
||||||
template<class F>
|
template<class F>
|
||||||
struct IsDestroyed
|
struct IsDestroyed
|
||||||
{
|
{
|
||||||
|
@ -685,33 +687,33 @@ namespace Loki
|
||||||
{
|
{
|
||||||
Followers<Master>::AddFollower(pFun);
|
Followers<Master>::AddFollower(pFun);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnDeadReference()
|
static void OnDeadReference()
|
||||||
{
|
{
|
||||||
throw std::logic_error("Dead Reference Detected");
|
throw std::logic_error("Dead Reference Detected");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
typename FollowIntoDeath::Followers<T>::Container*
|
typename FollowIntoDeath::Followers<T>::Container*
|
||||||
FollowIntoDeath::Followers<T>::followers_ = 0;
|
FollowIntoDeath::Followers<T>::followers_ = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \class SingletonHolder
|
/// \class SingletonHolder
|
||||||
///
|
///
|
||||||
/// \ingroup SingletonGroup
|
/// \ingroup SingletonGroup
|
||||||
///
|
///
|
||||||
/// Provides Singleton amenities for a type T
|
/// Provides Singleton amenities for a type T
|
||||||
/// To protect that type from spurious instantiations,
|
/// To protect that type from spurious instantiations,
|
||||||
/// you have to protect it yourself.
|
/// you have to protect it yourself.
|
||||||
///
|
///
|
||||||
/// \param CreationPolicy Creation policy, default: CreateUsingNew
|
/// \param CreationPolicy Creation policy, default: CreateUsingNew
|
||||||
/// \param LifetimePolicy Lifetime policy, default: DefaultLifetime,
|
/// \param LifetimePolicy Lifetime policy, default: DefaultLifetime,
|
||||||
/// \param ThreadingModel Threading policy,
|
/// \param ThreadingModel Threading policy,
|
||||||
/// default: LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL
|
/// default: LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template
|
template
|
||||||
|
@ -731,21 +733,21 @@ namespace Loki
|
||||||
|
|
||||||
/// Returns a reference to singleton object
|
/// Returns a reference to singleton object
|
||||||
static T& Instance();
|
static T& Instance();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Helpers
|
// Helpers
|
||||||
static void MakeInstance();
|
static void MakeInstance();
|
||||||
static void LOKI_C_CALLING_CONVENTION_QUALIFIER DestroySingleton();
|
static void LOKI_C_CALLING_CONVENTION_QUALIFIER DestroySingleton();
|
||||||
|
|
||||||
// Protection
|
// Protection
|
||||||
SingletonHolder();
|
SingletonHolder();
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
typedef typename ThreadingModel<T*,MutexPolicy>::VolatileType PtrInstanceType;
|
typedef typename ThreadingModel<T*,MutexPolicy>::VolatileType PtrInstanceType;
|
||||||
static PtrInstanceType pInstance_;
|
static PtrInstanceType pInstance_;
|
||||||
static bool destroyed_;
|
static bool destroyed_;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// SingletonHolder's data
|
// SingletonHolder's data
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -783,7 +785,7 @@ namespace Loki
|
||||||
template <class, class> class ThreadingModel,
|
template <class, class> class ThreadingModel,
|
||||||
class MutexPolicy
|
class MutexPolicy
|
||||||
>
|
>
|
||||||
inline T& SingletonHolder<T, CreationPolicy,
|
inline T& SingletonHolder<T, CreationPolicy,
|
||||||
LifetimePolicy, ThreadingModel, MutexPolicy>::Instance()
|
LifetimePolicy, ThreadingModel, MutexPolicy>::Instance()
|
||||||
{
|
{
|
||||||
if (!pInstance_)
|
if (!pInstance_)
|
||||||
|
@ -805,12 +807,12 @@ namespace Loki
|
||||||
template <class, class> class ThreadingModel,
|
template <class, class> class ThreadingModel,
|
||||||
class MutexPolicy
|
class MutexPolicy
|
||||||
>
|
>
|
||||||
void SingletonHolder<T, CreationPolicy,
|
void SingletonHolder<T, CreationPolicy,
|
||||||
LifetimePolicy, ThreadingModel, MutexPolicy>::MakeInstance()
|
LifetimePolicy, ThreadingModel, MutexPolicy>::MakeInstance()
|
||||||
{
|
{
|
||||||
typename ThreadingModel<SingletonHolder,MutexPolicy>::Lock guard;
|
typename ThreadingModel<SingletonHolder,MutexPolicy>::Lock guard;
|
||||||
(void)guard;
|
(void)guard;
|
||||||
|
|
||||||
if (!pInstance_)
|
if (!pInstance_)
|
||||||
{
|
{
|
||||||
if (destroyed_)
|
if (destroyed_)
|
||||||
|
@ -819,7 +821,7 @@ namespace Loki
|
||||||
destroyed_ = false;
|
destroyed_ = false;
|
||||||
}
|
}
|
||||||
pInstance_ = CreationPolicy<T>::Create();
|
pInstance_ = CreationPolicy<T>::Create();
|
||||||
LifetimePolicy<T>::ScheduleDestruction(pInstance_,
|
LifetimePolicy<T>::ScheduleDestruction(pInstance_,
|
||||||
&DestroySingleton);
|
&DestroySingleton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -832,7 +834,7 @@ namespace Loki
|
||||||
template <class, class> class M,
|
template <class, class> class M,
|
||||||
class X
|
class X
|
||||||
>
|
>
|
||||||
void LOKI_C_CALLING_CONVENTION_QUALIFIER
|
void LOKI_C_CALLING_CONVENTION_QUALIFIER
|
||||||
SingletonHolder<T, CreationPolicy, L, M, X>::DestroySingleton()
|
SingletonHolder<T, CreationPolicy, L, M, X>::DestroySingleton()
|
||||||
{
|
{
|
||||||
assert(!destroyed_);
|
assert(!destroyed_);
|
||||||
|
@ -849,7 +851,7 @@ namespace Loki
|
||||||
///
|
///
|
||||||
/// Convenience template to implement a getter function for a singleton object.
|
/// Convenience template to implement a getter function for a singleton object.
|
||||||
/// Often needed in a shared library which hosts singletons.
|
/// Often needed in a shared library which hosts singletons.
|
||||||
///
|
///
|
||||||
/// \par Usage
|
/// \par Usage
|
||||||
///
|
///
|
||||||
/// see test/SingletonDll
|
/// see test/SingletonDll
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue