Menu

alternative singleton lifetime tracker

Anonymous
2002-07-25
2002-07-28
  • Anonymous

    Anonymous - 2002-07-25

    I'd like to tell about singleton lifetime tracker I use by myself. The alternative lifetime tracking uses linked list of Lifetime objects insead of dynamic array. Since each singleton has only one Lifetime object, these objects are actually statics and there is no memory reallocation.
    This strategy allows to define dependencies between singletons instead of operate with arbitrary longevity numbers.
    I have three lifetime policies: the default that pushes the object to the lifetime list, the long lifetime that appends the object to the end, and third one allows to define singleton dependancies.
    The code is provided below:

    class LifetimeBase
    {
    protected:
        LifetimeBase()
            : m_pNext(0), m_InList(false)
        {
            if (!m_pHeader)
            {
                atexit(DeleteAll);
            }
        }

        ~LifetimeBase() {}

        virtual void DeleteInstance() = 0;

    public:
        LifetimeBase        *m_pNext;
        bool                m_InList;

        static LifetimeBase    *m_pHeader;

    private:
        static void DeleteAll()
        {
            for (LifetimeBase *p = m_pHeader; p; p = p->m_pNext)
            {
                p->DeleteInstance();
            }
        }
    };

    LifetimeBase *LifetimeBase::m_pHeader = 0;

    template <class T>
    class Lifetime: public LifetimeBase
    {
    public:
        typedef void (*Destructor)();

    //    static void ScheduleDestruction(T*, Destructor d)
    //    { throw std::logic_error("abstract call"); }

        void Init(T *host, Destructor dtor)
        {
            if (!m_pHost)
            {
                m_pHost = host;
                m_Dtor    = dtor;
            }
        }
       
        static void OnDeadReference()
        { throw std::logic_error("Dead Reference Detected"); }

        static Lifetime<T> &Instance()
        {
            if (!m_pInstance)
            {
                CreateInstance();
            }

            return *m_pInstance;
        }

        ~Lifetime() {}

    protected:
        Lifetime()
            : m_pHost(0), m_Dtor(0) {}

        static Lifetime<T> *CreateInstance()
        {
            // ### critical section lock
            if (!m_pInstance)
            {
                enum {alignment = 2*sizeof(size_t), alignMask = alignment - 1};
                static char    placement[sizeof(Lifetime<T>) + alignment];

                char *p        = (char *)(size_t(placement + alignMask) & ~alignMask);
                m_pInstance = new (p) Lifetime<T>;
            }

            return m_pInstance;
        }

        virtual void DeleteInstance()
        {
            if (m_pHost)
            {
                m_Dtor();
                m_pHost = 0;
            }
        }

        T            *m_pHost;
        Destructor    m_Dtor;

    private:
        static Lifetime<T> *m_pInstance;
    };

    template <class T>
    Lifetime<T> *Lifetime<T>::m_pInstance = 0;

    template <class T>
    class DefaultLifetime: public Lifetime<T>
    {
    public:
        static void ScheduleDestruction(T *host, Destructor dtor)
        {
            // ### critical section
            Lifetime<T> &lt = Lifetime<T>::Instance();
            lt.Init(host, dtor);

            if (!lt.m_InList)
            {
                lt.m_pNext    = m_pHeader;
                m_pHeader    = &lt;

                lt.m_InList    = true;
            }
        }
    };

    template <class T>
    class LongLifetime: public Lifetime<T>
    {
    public:
        static void ScheduleDestruction(T *host, Destructor dtor)
        {
            // ### critical section
            Lifetime<T> &lt = Lifetime<T>::Instance();
            lt.Init(host, dtor);

            if (lt.m_InList)
            {
                // reschedule

                // search in list
                LifetimeBase *prev = 0;
                for (LifetimeBase *p = m_pHeader;
                        p; prev = p, p = p->m_pNext)
                {
                    if (p == &lt)
                    {
                        break;
                    }
                }

                // remove
                if (prev)
                {
                    prev->m_pNext = p->m_pNext;
                }
                else
                {
                    m_pHeader = p->m_pNext;
                }
            }

            // insert at the end
            if (!m_pHeader)
            {
                m_pHeader = &lt;
            }
            else
            {
                LifetimeBase *p = m_pHeader;
                while (p->m_pNext) p = p->m_pNext;

                p->m_pNext = &lt;
            }

            lt.m_InList    = true;
        }
    };

    template <class TDependant, class TPredominant>
    class DependantLifetime: public Lifetime<TDependant>
    {
    public:
        static void ScheduleDestruction(TDependant *host, Destructor dtor)
        {
            // ### critical section

            Lifetime<TDependant> &dependant =
                Lifetime<TDependant>::Instance();

            Lifetime<TPredominant> &predominant =
                Lifetime<TPredominant>::Instance();

            dependant.Init(host, dtor);

            if (!dependant.m_InList)
            {
                if (!predominant.m_InList)
                {
                    predominant.m_pNext        = m_pHeader;
                    m_pHeader                = &predominant;
                    predominant.m_InList    = true;
                }

                dependant.m_pNext    = m_pHeader;
                m_pHeader            = &dependant;
                dependant.m_InList    = true;
            }
        }
    };

     
    • Shannon Glenn Barber

      A loki-experimental project has been setup for proposed extentions & additions.

      http://sourceforge.net/projects/loki-exp/

       

Log in to post a comment.