⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 singleton.h

📁 Windows Mobile平台上使用GDI+。GDI+功能很强大
💻 H
📖 第 1 页 / 共 2 页
字号:
////////////////////////////////////////////////////////////////////////////////// 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();        }    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -