diff options
Diffstat (limited to 'shared/loki/Singleton.h')
-rw-r--r-- | shared/loki/Singleton.h | 889 |
1 files changed, 0 insertions, 889 deletions
diff --git a/shared/loki/Singleton.h b/shared/loki/Singleton.h deleted file mode 100644 index 1e479032..00000000 --- a/shared/loki/Singleton.h +++ /dev/null @@ -1,889 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// The Loki Library -// Copyright (c) 2001 by Andrei Alexandrescu -// This code accompanies the book: -// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design -// Patterns Applied". Copyright (c) 2001. Addison-Wesley. -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this -// permission notice appear in supporting documentation. -// The author or Addison-Wesley Longman make no representations about the -// suitability of this software for any purpose. It is provided "as is" -// without express or implied warranty. -//////////////////////////////////////////////////////////////////////////////// -#ifndef LOKI_SINGLETON_INC_ -#define LOKI_SINGLETON_INC_ - -// $Id: Singleton.h 834 2007-08-02 19:36:10Z syntheticpp $ - - -#include "LokiExport.h" -#include "Threads.h" -#include <algorithm> -#include <stdexcept> -#include <cassert> -#include <cstdlib> -#include <new> -#include <vector> -#include <list> -#include <memory> - -#ifdef _MSC_VER -#define LOKI_C_CALLING_CONVENTION_QUALIFIER __cdecl -#else -#define LOKI_C_CALLING_CONVENTION_QUALIFIER -#endif - -/// \defgroup SingletonGroup Singleton -/// \defgroup CreationGroup Creation policies -/// \ingroup SingletonGroup -/// \defgroup LifetimeGroup Lifetime policies -/// \ingroup SingletonGroup -/// The lifetimes of the singleton. -/// \par Special lifetime for SmallObjects -/// When the holded object is a Small(Value)Object or the holded object -/// uses objects which are or inherit from Small(Value)Object -/// then you can't use the default lifetime: you must use the lifetime -/// \code Loki::LongevityLifetime::DieAsSmallObjectChild \endcode -/// Be aware of this when you use Loki::Factory, Loki::Functor, or Loki::Function. - - - -namespace Loki -{ -typedef void (LOKI_C_CALLING_CONVENTION_QUALIFIER* atexit_pfn_t)(); - -namespace Private -{ - -#ifndef LOKI_MAKE_DLL -void LOKI_C_CALLING_CONVENTION_QUALIFIER AtExitFn(); // declaration needed below -#else -void LOKI_EXPORT AtExitFn(); -#endif - -class LifetimeTracker; - -#define LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL -#ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL - -// Helper data -// std::list because of the inserts -typedef std::list<LifetimeTracker*> TrackerArray; -extern LOKI_EXPORT TrackerArray* pTrackerArray; -#else -// Helper data -typedef LifetimeTracker** TrackerArray; -extern TrackerArray pTrackerArray; -extern unsigned int elements; -#endif - -//////////////////////////////////////////////////////////////////////////////// -// class LifetimeTracker -// Helper class for SetLongevity -//////////////////////////////////////////////////////////////////////////////// - -class LifetimeTracker -{ -public: - LifetimeTracker(unsigned int x) : longevity_(x) - {} - - virtual ~LifetimeTracker() = 0; - - static bool Compare(const LifetimeTracker* lhs, - const LifetimeTracker* rhs) - { - return lhs->longevity_ > rhs->longevity_; - } - -private: - unsigned int longevity_; -}; - -// Definition required -inline LifetimeTracker::~LifetimeTracker() {} - -// Helper destroyer function -template <typename T> -struct Deleter -{ - typedef void (*Type)(T*); - static void Delete(T* pObj) - { delete pObj; } -}; - -// Concrete lifetime tracker for objects of type T -template <typename T, typename Destroyer> -class ConcreteLifetimeTracker : public LifetimeTracker -{ -public: - ConcreteLifetimeTracker(T* p, unsigned int longevity, Destroyer d) - : LifetimeTracker(longevity) - , pTracked_(p) - , destroyer_(d) - {} - - ~ConcreteLifetimeTracker() - { destroyer_(pTracked_); } - -private: - T* pTracked_; - Destroyer destroyer_; -}; - -} // namespace Private - -//////////////////////////////////////////////////////////////////////////////// -/// \ingroup LifetimeGroup -/// -/// Assigns an object a longevity; ensures ordered destructions of objects -/// registered thusly during the exit sequence of the application -//////////////////////////////////////////////////////////////////////////////// - -#ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL - -template <typename T, typename Destroyer> -void SetLongevity(T* pDynObject, unsigned int longevity, - Destroyer d) -{ - using namespace Private; - - // manage lifetime of stack manually - if (pTrackerArray == 0) - pTrackerArray = new TrackerArray; - - // automatically delete the ConcreteLifetimeTracker object when a exception is thrown - std::auto_ptr<LifetimeTracker> - p( new ConcreteLifetimeTracker<T, Destroyer>(pDynObject, longevity, d) ); - - // Find correct position - TrackerArray::iterator pos = std::upper_bound( - pTrackerArray->begin(), - pTrackerArray->end(), - p.get(), - LifetimeTracker::Compare); - - // Insert the pointer to the ConcreteLifetimeTracker object into the queue - pTrackerArray->insert(pos, p.get()); - - // nothing has thrown: don't delete the ConcreteLifetimeTracker object - p.release(); - - // Register a call to AtExitFn - std::atexit(Private::AtExitFn); -} - -#else - -template <typename T, typename Destroyer> -void SetLongevity(T* pDynObject, unsigned int longevity, - Destroyer d) -{ - using namespace Private; - - TrackerArray pNewArray = static_cast<TrackerArray>( - std::realloc(pTrackerArray, - sizeof(*pTrackerArray) * (elements + 1))); - if (!pNewArray) throw std::bad_alloc(); - - // Delayed assignment for exception safety - pTrackerArray = pNewArray; - - LifetimeTracker* p = new ConcreteLifetimeTracker<T, Destroyer>( - pDynObject, longevity, d); - - // Insert a pointer to the object into the queue - TrackerArray pos = std::upper_bound( - pTrackerArray, - pTrackerArray + elements, - p, - LifetimeTracker::Compare); - std::copy_backward( - pos, - pTrackerArray + elements, - pTrackerArray + elements + 1); - *pos = p; - ++elements; - - // Register a call to AtExitFn - std::atexit(Private::AtExitFn); -} - -#endif - -template <typename T> -void SetLongevity(T* pDynObject, unsigned int longevity, - typename Private::Deleter<T>::Type d = Private::Deleter<T>::Delete) -{ - SetLongevity<T, typename Private::Deleter<T>::Type>(pDynObject, longevity, d); -} - -//////////////////////////////////////////////////////////////////////////////// -/// \struct CreateUsingNew -/// -/// \ingroup CreationGroup -/// Implementation of the CreationPolicy used by SingletonHolder -/// Creates objects using a straight call to the new operator -//////////////////////////////////////////////////////////////////////////////// -template <class T> struct CreateUsingNew -{ - static T* Create() - { return new T; } - - static void Destroy(T* p) - { delete p; } -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct CreateUsing -/// -/// \ingroup CreationGroup -/// Implementation of the CreationPolicy used by SingletonHolder -/// Creates objects using a custom allocater. -/// Usage: e.g. CreateUsing<std::allocator>::Allocator -//////////////////////////////////////////////////////////////////////////////// -template<template<class> class Alloc> -struct CreateUsing -{ - template <class T> - struct Allocator - { - static Alloc<T> allocator; - - static T* Create() - { - return new (allocator.allocate(1)) T; - } - - static void Destroy(T* p) - { - //allocator.destroy(p); - p->~T(); - allocator.deallocate(p, 1); - } - }; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct CreateUsingMalloc -/// -/// \ingroup CreationGroup -/// Implementation of the CreationPolicy used by SingletonHolder -/// Creates objects using a call to std::malloc, followed by a call to the -/// placement new operator -//////////////////////////////////////////////////////////////////////////////// -template <class T> struct CreateUsingMalloc -{ - static T* Create() - { - void* p = std::malloc(sizeof(T)); - if (!p) return 0; - return new(p) T; - } - - static void Destroy(T* p) - { - p->~T(); - std::free(p); - } -}; - - -//////////////////////////////////////////////////////////////////////////////// -/// \struct CreateStatic -/// -/// \ingroup CreationGroup -/// Implementation of the CreationPolicy used by SingletonHolder -/// Creates an object in static memory -/// Implementation is slightly nonportable because it uses the MaxAlign trick -/// (an union of all types to ensure proper memory alignment). This trick is -/// nonportable in theory but highly portable in practice. -//////////////////////////////////////////////////////////////////////////////// -template <class T> struct CreateStatic -{ - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4121 ) - // alignment of a member was sensitive to packing -#endif // _MSC_VER - - union MaxAlign - { - char t_[sizeof(T)]; - short int shortInt_; - int int_; - long int longInt_; - float float_; - double double_; - long double longDouble_; - struct Test; - int Test::* pMember_; - int (Test::*pMemberFn_)(int); - }; - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif // _MSC_VER - - static T* Create() - { - static MaxAlign staticMemory_; - return new(&staticMemory_) T; - } - - static void Destroy(T* p) - { - p->~T(); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct DefaultLifetime -/// -/// \ingroup LifetimeGroup -/// Implementation of the LifetimePolicy used by SingletonHolder -/// Schedules an object's destruction as per C++ rules -/// Forwards to std::atexit -//////////////////////////////////////////////////////////////////////////////// -template <class T> -struct DefaultLifetime -{ - static void ScheduleDestruction(T*, atexit_pfn_t pFun) - { std::atexit(pFun); } - - static void OnDeadReference() - { throw std::logic_error("Dead Reference Detected"); } -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct PhoenixSingleton -/// -/// \ingroup LifetimeGroup -/// Implementation of the LifetimePolicy used by SingletonHolder -/// Schedules an object's destruction as per C++ rules, and it allows object -/// recreation by not throwing an exception from OnDeadReference -//////////////////////////////////////////////////////////////////////////////// -template <class T> -class PhoenixSingleton -{ -public: - static void ScheduleDestruction(T*, atexit_pfn_t pFun) - { -#ifndef ATEXIT_FIXED - if (!destroyedOnce_) -#endif - std::atexit(pFun); - } - - static void OnDeadReference() - { -#ifndef ATEXIT_FIXED - destroyedOnce_ = true; -#endif - } - -private: -#ifndef ATEXIT_FIXED - static bool destroyedOnce_; -#endif -}; - -#ifndef ATEXIT_FIXED -template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false; -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Copyright (c) 2004 by Curtis Krauskopf - curtis@decompile.com -/// -/// \struct DeletableSingleton -/// -/// \ingroup LifetimeGroup -/// -/// A DeletableSingleton allows the instantiated singleton to be -/// destroyed at any time. The singleton can be reinstantiated at -/// any time, even during program termination. -/// If the singleton exists when the program terminates, it will -/// be automatically deleted. -/// -/// \par Usage: -/// The singleton can be deleted manually: -/// -/// DeletableSingleton<MyClass>::GracefulDelete(); -//////////////////////////////////////////////////////////////////////////////// -template <class T> -class DeletableSingleton -{ -public: - - static void ScheduleDestruction(T*, atexit_pfn_t pFun) - { - static bool firstPass = true; - isDead = false; - deleter = pFun; - if (firstPass || needCallback) - { - std::atexit(atexitCallback); - firstPass = false; - needCallback = false; - } - } - - static void OnDeadReference() - { - } - /// delete singleton object manually - static void GracefulDelete() - { - if (isDead) - return; - isDead = true; - deleter(); - } - -protected: - static atexit_pfn_t deleter; - static bool isDead; - static bool needCallback; - - static void atexitCallback() - { -#ifdef ATEXIT_FIXED - needCallback = true; -#else - needCallback = false; -#endif - GracefulDelete(); - } -}; - -template <class T> -atexit_pfn_t DeletableSingleton<T>::deleter = 0; - -template <class T> -bool DeletableSingleton<T>::isDead = true; - -template <class T> -bool DeletableSingleton<T>::needCallback = true; - -//////////////////////////////////////////////////////////////////////////////// -// class template Adapter -// Helper for SingletonWithLongevity below -//////////////////////////////////////////////////////////////////////////////// - -namespace Private -{ -template <class T> -struct Adapter -{ - void operator()(T*) { return pFun_(); } - atexit_pfn_t pFun_; -}; -} - -//////////////////////////////////////////////////////////////////////////////// -/// \struct SingletonWithLongevity -/// -/// \ingroup LifetimeGroup -/// Implementation of the LifetimePolicy used by SingletonHolder -/// Schedules an object's destruction in order of their longevities -/// Assumes a visible function GetLongevity(T*) that returns the longevity of the -/// object. -//////////////////////////////////////////////////////////////////////////////// -template <class T> -class SingletonWithLongevity -{ -public: - static void ScheduleDestruction(T* pObj, atexit_pfn_t pFun) - { - Private::Adapter<T> adapter = { pFun }; - SetLongevity(pObj, GetLongevity(pObj), adapter); - } - - static void OnDeadReference() - { throw std::logic_error("Dead Reference Detected"); } -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct NoDestroy -/// -/// \ingroup LifetimeGroup -/// Implementation of the LifetimePolicy used by SingletonHolder -/// Never destroys the object -//////////////////////////////////////////////////////////////////////////////// -template <class T> -struct NoDestroy -{ - static void ScheduleDestruction(T*, atexit_pfn_t) - {} - - static void OnDeadReference() - {} -}; - - -//////////////////////////////////////////////////////////////////////////////// -/// \defgroup LongevityLifetimeGroup LongevityLifetime -/// \ingroup LifetimeGroup -/// -/// \namespace LongevityLifetime -/// -/// \ingroup LongevityLifetimeGroup -/// \brief In this namespace are special lifetime policies to manage lifetime -/// dependencies. -//////////////////////////////////////////////////////////////////////////////// -namespace LongevityLifetime -{ -//////////////////////////////////////////////////////////////////////////////// -/// \struct SingletonFixedLongevity -/// -/// \ingroup LongevityLifetimeGroup -/// Add your own lifetimes into the namespace 'LongevityLifetime' -/// with your prefered lifetime by adding a struct like this: -/// -/// template<class T> -/// struct MyLifetime : SingletonFixedLongevity< MyLifetimeNumber ,T> {} -//////////////////////////////////////////////////////////////////////////////// -template <unsigned int Longevity, class T> -class SingletonFixedLongevity -{ -public: - virtual ~SingletonFixedLongevity() {} - - static void ScheduleDestruction(T* pObj, atexit_pfn_t pFun) - { - Private::Adapter<T> adapter = { pFun }; - SetLongevity(pObj, Longevity , adapter); - } - - static void OnDeadReference() - { throw std::logic_error("Dead Reference Detected"); } -}; - -/// \struct DieLast -/// \ingroup LongevityLifetimeGroup -/// \brief Longest possible SingletonWithLongevity lifetime: 0xFFFFFFFF -template <class T> -struct DieLast : SingletonFixedLongevity<0xFFFFFFFF , T> -{}; - -/// \struct DieDirectlyBeforeLast -/// \ingroup LongevityLifetimeGroup -/// \brief Lifetime is a one less than DieLast: 0xFFFFFFFF-1 -template <class T> -struct DieDirectlyBeforeLast : SingletonFixedLongevity < 0xFFFFFFFF - 1 , T > -{}; - -/// \struct DieFirst -/// \ingroup LongevityLifetimeGroup -/// \brief Shortest possible SingletonWithLongevity lifetime: 0 -template <class T> -struct DieFirst : SingletonFixedLongevity<0, T> -{}; - -}//namespace LongevityLifetime - -//////////////////////////////////////////////////////////////////////////////// -/// \class FollowIntoDeath -/// -/// \ingroup LifetimeGroup -/// -/// Lifetime policyfor the SingletonHolder tempalte. -/// Followers will die after the master dies Followers will not die, if -/// - master never dies (NoDestroy policy) -/// - master never created -/// - master dies not in the function registered with atexit -/// - master dies not by a call of a the atexit registerd function (DeletableSingleton::GracefulDelete) -/// -/// \par Usage: -/// -/// Lifetimes of the master and the follower singletons, e.g. with a M and a F class: -/// \code SingletonHolder< M , FollowIntoDeath::With<DefaultLifetime>::AsMasterLifetime > MasterSingleton; \endcode -/// \code SingletonHolder< F , CreateUsingNew, FollowIntoDeath::AfterMaster< MasterSingleton >::IsDestroyed > FollowerSingleton \endcode -//////////////////////////////////////////////////////////////////////////////// -class FollowIntoDeath -{ - template<class T> - class Followers - { - typedef std::vector<atexit_pfn_t> Container; - typedef typename Container::iterator iterator; - static Container* followers_; - - public: - static void Init() - { - static bool done = false; - if (!done) - { - followers_ = new Container; - done = true; - } - } - - static void AddFollower(atexit_pfn_t ae) - { - Init(); - followers_->push_back(ae); - } - - static void DestroyFollowers() - { - Init(); - for (iterator it = followers_->begin(); it != followers_->end(); ++it) - (*it)(); - delete followers_; - } - }; - -public: - - /// \struct With - /// Template for the master - /// \param Lifetime Lifetime policy for the master - template<template <class> class Lifetime> - struct With - { - /// \struct AsMasterLifetime - /// Policy for master - template<class Master> - struct AsMasterLifetime - { - static void ScheduleDestruction(Master* pObj, atexit_pfn_t pFun) - { - Followers<Master>::Init(); - Lifetime<Master>::ScheduleDestruction(pObj, pFun); - - // use same policy for the followers and force a new - // template instantiation, this adds a additional atexit entry - // does not work with SetLonlevity, but there you can control - // the lifetime with the GetLongevity function. - Lifetime<Followers<Master> >::ScheduleDestruction(0, Followers<Master>::DestroyFollowers); - } - - static void OnDeadReference() - { - throw std::logic_error("Dead Reference Detected"); - } - }; - }; - - /// \struct AfterMaster - /// Template for the follower - /// \param Master Master to follow into death - template<class Master> - struct AfterMaster - { - /// \struct IsDestroyed - /// Policy for followers - template<class F> - struct IsDestroyed - { - static void ScheduleDestruction(F*, atexit_pfn_t pFun) - { - Followers<Master>::AddFollower(pFun); - } - - static void OnDeadReference() - { - throw std::logic_error("Dead Reference Detected"); - } - }; - }; -}; - -template<class T> -typename FollowIntoDeath::Followers<T>::Container* -FollowIntoDeath::Followers<T>::followers_ = 0; - - - -//////////////////////////////////////////////////////////////////////////////// -/// \class SingletonHolder -/// -/// \ingroup SingletonGroup -/// -/// Provides Singleton amenities for a type T -/// To protect that type from spurious instantiations, -/// you have to protect it yourself. -/// -/// \param CreationPolicy Creation policy, default: CreateUsingNew -/// \param LifetimePolicy Lifetime policy, default: DefaultLifetime, -/// \param ThreadingModel Threading policy, -/// default: LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL -//////////////////////////////////////////////////////////////////////////////// -template -< -typename T, - template <class> class CreationPolicy = CreateUsingNew, - template <class> class LifetimePolicy = DefaultLifetime, - template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL, - class MutexPolicy = LOKI_DEFAULT_MUTEX - > -class SingletonHolder -{ -public: - - /// Type of the singleton object - typedef T ObjectType; - - /// Returns a reference to singleton object - static T& Instance(); - -private: - // Helpers - static void MakeInstance(); - static void LOKI_C_CALLING_CONVENTION_QUALIFIER DestroySingleton(); - - // Protection - SingletonHolder(); - - // Data - typedef typename ThreadingModel<T*, MutexPolicy>::VolatileType PtrInstanceType; - static PtrInstanceType pInstance_; - static bool destroyed_; -}; - -//////////////////////////////////////////////////////////////////////////////// -// SingletonHolder's data -//////////////////////////////////////////////////////////////////////////////// - -template -< -class T, - template <class> class C, - template <class> class L, - template <class, class> class M, - class X - > -typename SingletonHolder<T, C, L, M, X>::PtrInstanceType -SingletonHolder<T, C, L, M, X>::pInstance_ = 0; - -template -< -class T, - template <class> class C, - template <class> class L, - template <class, class> class M, - class X - > -bool SingletonHolder<T, C, L, M, X>::destroyed_ = false; - -//////////////////////////////////////////////////////////////////////////////// -// SingletonHolder::Instance -//////////////////////////////////////////////////////////////////////////////// - -template -< -class T, - template <class> class CreationPolicy, - template <class> class LifetimePolicy, - template <class, class> class ThreadingModel, - class MutexPolicy - > -inline T& SingletonHolder < T, CreationPolicy, - LifetimePolicy, ThreadingModel, MutexPolicy >::Instance() -{ - if (!pInstance_) - { - MakeInstance(); - } - return *pInstance_; -} - -//////////////////////////////////////////////////////////////////////////////// -// SingletonHolder::MakeInstance (helper for Instance) -//////////////////////////////////////////////////////////////////////////////// - -template -< -class T, -template <class> class CreationPolicy, -template <class> class LifetimePolicy, -template <class, class> class ThreadingModel, -class MutexPolicy -> -void SingletonHolder < T, CreationPolicy, - LifetimePolicy, ThreadingModel, MutexPolicy >::MakeInstance() -{ - typename ThreadingModel<SingletonHolder, MutexPolicy>::Lock guard; - (void)guard; - - if (!pInstance_) - { - if (destroyed_) - { - destroyed_ = false; - LifetimePolicy<T>::OnDeadReference(); - } - pInstance_ = CreationPolicy<T>::Create(); - LifetimePolicy<T>::ScheduleDestruction(pInstance_, - &DestroySingleton); - } -} - -template -< -class T, -template <class> class CreationPolicy, -template <class> class L, -template <class, class> class M, -class X -> -void LOKI_C_CALLING_CONVENTION_QUALIFIER -SingletonHolder<T, CreationPolicy, L, M, X>::DestroySingleton() -{ - assert(!destroyed_); - CreationPolicy<T>::Destroy(pInstance_); - pInstance_ = 0; - destroyed_ = true; -} - - -//////////////////////////////////////////////////////////////////////////////// -/// \class Singleton -/// -/// \ingroup SingletonGroup -/// -/// Convenience template to implement a getter function for a singleton object. -/// Often needed in a shared library which hosts singletons. -/// -/// \par Usage -/// -/// see test/SingletonDll -/// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef LOKI_SINGLETON_EXPORT -#define LOKI_SINGLETON_EXPORT -#endif - -template<class T> -class LOKI_SINGLETON_EXPORT Singleton -{ -public: - static T& Instance(); -}; - -} // namespace Loki - - -/// \def LOKI_SINGLETON_INSTANCE_DEFINITION(SHOLDER) -/// Convenience macro for the definition of the static Instance member function -/// Put this macro called with a SingletonHolder typedef into your cpp file. - -#define LOKI_SINGLETON_INSTANCE_DEFINITION(SHOLDER) \ - namespace Loki \ - { \ - template<> \ - SHOLDER::ObjectType& Singleton<SHOLDER::ObjectType>::Instance() \ - { \ - return SHOLDER::Instance(); \ - } \ - } - - -#endif // end file guardian - |