singleton.h

来自「C++封装的视频采集代码」· C头文件 代码 · 共 460 行

H
460
字号
////////////////////////////////////////////////////////////////////////////////// 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.////////////////////////////////////////////////////////////////////////////////// Last update: August 9, 2002#ifndef SINGLETON_INC_#define SINGLETON_INC_#include "Threads.h"#include <algorithm>#ifndef OXSEMI_NO_EXCEPTIONS#include <stdexcept>#endif#include "Utils/assert.h"#include "Utils/excdef.h"#include <cstdlib>#include <new>#include <string>#ifdef __BORLANDC__#  define ATEXIT_FIXED#endifnamespace Loki{    namespace Private    {////////////////////////////////////////////////////////////////////////////////// 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 data        typedef LifetimeTracker** TrackerArray;        extern TrackerArray pTrackerArray;        extern unsigned int elements;        // Helper destroyer function        template <typename T>        struct Deleter        {            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_;        };        void AtExitFn(); // declaration needed below        } // namespace Private////////////////////////////////////////////////////////////////////////////////// function template SetLongevity// Assigns an object a longevity; ensures ordered destructions of objects //     registered thusly during the exit sequence of the application////////////////////////////////////////////////////////////////////////////////    template <typename T, typename Destroyer>    void SetLongevity(T* pDynObject, unsigned int longevity,        Destroyer d = Private::Deleter<T>::Delete)    {        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);    }////////////////////////////////////////////////////////////////////////////////// class template CreateUsingNew// 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; }    };    ////////////////////////////////////////////////////////////////////////////////// class template CreateUsingNew// 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);        }    };    ////////////////////////////////////////////////////////////////////////////////// class template CreateStatic// 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    {        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);        };                static T* Create()        {            static MaxAlign staticMemory_;            return new(&staticMemory_) T;        }                static void Destroy(T* p)        {            p->~T();        }    };    ////////////////////////////////////////////////////////////////////////////////// class template DefaultLifetime// 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*, void (*pFun)())        { std::atexit(pFun); }                static void OnDeadReference()        { THROW (std::logic_error(std::string("Dead Reference Detected"))); }    };////////////////////////////////////////////////////////////////////////////////// class template PhoenixSingleton// 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*, void (*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        ////////////////////////////////////////////////////////////////////////////////// class template Adapter// Helper for SingletonWithLongevity below////////////////////////////////////////////////////////////////////////////////    namespace Private    {        template <class T>        struct Adapter        {            void operator()(T*) { return pFun_(); }            void (*pFun_)();        };    }////////////////////////////////////////////////////////////////////////////////// class template SingletonWithLongevity// 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, void (*pFun)())        {            Private::Adapter<T> adapter = { pFun };            SetLongevity(pObj, GetLongevity(pObj), adapter);        }                static void OnDeadReference()        { THROW (std::logic_error(std::string("Dead Reference Detected"))); }    };////////////////////////////////////////////////////////////////////////////////// class template NoDestroy// Implementation of the LifetimePolicy used by SingletonHolder// Never destroys the object////////////////////////////////////////////////////////////////////////////////    template <class T>    struct NoDestroy    {        static void ScheduleDestruction(T*, void (*)())        {}                static void OnDeadReference()        {}    };////////////////////////////////////////////////////////////////////////////////// class template SingletonHolder// Provides Singleton amenities for a type T// To protect that type from spurious instantiations, you have to protect it//     yourself.////////////////////////////////////////////////////////////////////////////////    template    <        typename T,        template <class> class CreationPolicy = CreateUsingNew,        template <class> class LifetimePolicy = DefaultLifetime,        template <class> class ThreadingModel = SingleThreaded    >    class SingletonHolder    {    public:        static T& Instance();            private:        // Helpers        static void MakeInstance();        static void DestroySingleton();                // Protection        SingletonHolder();                // Data        typedef typename ThreadingModel<T*>::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 M    >    typename SingletonHolder<T, C, L, M>::PtrInstanceType        SingletonHolder<T, C, L, M>::pInstance_;    template    <        class T,        template <class> class C,        template <class> class L,        template <class> class M    >    bool SingletonHolder<T, C, L, M>::destroyed_;////////////////////////////////////////////////////////////////////////////////// SingletonHolder::Instance////////////////////////////////////////////////////////////////////////////////    template    <        class T,        template <class> class CreationPolicy,        template <class> class LifetimePolicy,        template <class> class ThreadingModel    >    inline T& SingletonHolder<T, CreationPolicy,         LifetimePolicy, ThreadingModel>::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 ThreadingModel    >    void SingletonHolder<T, CreationPolicy,         LifetimePolicy, ThreadingModel>::MakeInstance()    {        typename ThreadingModel<T>::Lock guard;        (void)guard;                if (!pInstance_)        {            if (destroyed_)            {                LifetimePolicy<T>::OnDeadReference();                destroyed_ = false;            }            pInstance_ = CreationPolicy<T>::Create();            LifetimePolicy<T>::ScheduleDestruction(pInstance_,                 &DestroySingleton);        }    }    template    <        class T,        template <class> class CreationPolicy,        template <class> class L,        template <class> class M    >    void SingletonHolder<T, CreationPolicy, L, M>::DestroySingleton()    {        ASSERT(!destroyed_);        CreationPolicy<T>::Destroy(pInstance_);        pInstance_ = 0;        destroyed_ = true;    }} // namespace Loki////////////////////////////////////////////////////////////////////////////////// Change log:// May     21, 2001: Correct the volatile qualifier - credit due to Darin Adler// June    20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!// January 08, 2002: Fixed bug in call to realloc - credit due to Nigel Gent and//                   Eike Petersen// March   08, 2002: moved the assignment to pTrackerArray in SetLongevity to fix//                   exception safety issue. Credit due to Kari Hoijarvi// May     09, 2002: Fixed bug in Compare that caused longevities to act backwards.//                   Credit due to Scott McDonald.// July    16, 2002: Ported by Terje Sletteb� and Pavel Vozenilek to BCC 5.6////////////////////////////////////////////////////////////////////////////////#endif // SINGLETON_INC_

⌨️ 快捷键说明

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