Phoenix Singletons

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • stephan beal

    Phoenix Singletons

    Good morning, C++ users,

    i've been hesitating to post this, primarily because i know that most of you
    here are *way* ahead of me in C++ and i'm a little embarassed about the
    possibility of some gross errors in what i'll be posting...

    That said, please go easy on me. :)

    About 2 weeks ago i wrote a paper, called Context Singletons, where i
    discuss some of the uses of context-specific Singleton-like objects. During
    the development of the paper i came up with a Phoenix class for providing
    Phoenixing behaviour (as defined in Alexandrescu's MC++D) to my Context
    Singletons. (http://s11n.net/misccode/)

    So what, right?

    i'm here to ask the Gurus to please take a look at my Phoenix, and see if
    i'm doing something Inherently Wrong here. My gut tells me that the
    implementation is simply too straightforward to solve the problem
    adequately, but practice shows that it works quite well :/.

    The source code is here:

    template < typename BaseType, typename ContextType = BaseType >
    class phoenix : public BaseType {
    public:
    typedef ContextType context_type;
    typedef BaseType base_type;
    static base_type & instance() {
    static this_type meyers;
    if( this_type::m_de stroyed ) {
    new( &meyers ) this_type;
    atexit( this_type::do_a texit );
    }
    return meyers;
    }
    private:
    typedef phoenix<base_ty pe,context_type > this_type;
    static bool m_destroyed;
    phoenix() { m_destroyed = false; }
    ~phoenix() { m_destroyed = true; }
    static void do_atexit() {
    if( m_destroyed ) return;
    static_cast<thi s_type SPMamp;>(instan ce()).~phoenix( );
    }
    };
    template <typename T, typename C> bool phoenix<T,C>::m _destroyed = false;

    This code is complete for purposes of the questions posed here, but the code
    at http://s11n.net/misccode/phoenix.h is "more complete", with docs,
    comments, one additional (optional) template parameter and debugging code.

    Regarding the implementation, i have these questions:

    - What happens when BaseType has a non-virtual destructor? We never use
    delete(), relying on static destruction instead, so i think this is safe. i
    have successfully used this class with, e.g., std::map<> as BaseType, but
    maybe i just have a remarkably accomodating C++ platform.

    - Is it possible that m_destroyed gets destroyed at a point such that the
    above usages of it becomes invalid? If so, is there a way to phoenix that
    bool, so to speak?


    Any insights on these points would be greatly appreciated.


    --
    ----- stephan beal

    Registered Linux User #71917 http://counter.li.org
    I speak for myself, not my employer. Contents may
    be hot. Slippery when wet. Reading disclaimers makes
    you go blind. Writing them is worse. You have been Warned.

  • Nick Hounsome

    #2
    Re: Phoenix Singletons

    It's undefined behaviour.
    You obviously know that it is undefined behaviour.
    Getting someone on this newsgroup to say it's OK wont make it so.

    "stephan beal" <stephan@s11n.n et> wrote in message
    news:bsr9l3$8og $1@ork.noris.ne t...[color=blue]
    > Good morning, C++ users,
    >
    > i've been hesitating to post this, primarily because i know that most of[/color]
    you[color=blue]
    > here are *way* ahead of me in C++ and i'm a little embarassed about the
    > possibility of some gross errors in what i'll be posting...
    >
    > That said, please go easy on me. :)
    >
    > About 2 weeks ago i wrote a paper, called Context Singletons, where i
    > discuss some of the uses of context-specific Singleton-like objects.[/color]
    During[color=blue]
    > the development of the paper i came up with a Phoenix class for providing
    > Phoenixing behaviour (as defined in Alexandrescu's MC++D) to my Context
    > Singletons. (http://s11n.net/misccode/)
    >
    > So what, right?
    >
    > i'm here to ask the Gurus to please take a look at my Phoenix, and see if
    > i'm doing something Inherently Wrong here. My gut tells me that the
    > implementation is simply too straightforward to solve the problem
    > adequately, but practice shows that it works quite well :/.
    >
    > The source code is here:
    >
    > template < typename BaseType, typename ContextType = BaseType >
    > class phoenix : public BaseType {
    > public:
    > typedef ContextType context_type;
    > typedef BaseType base_type;
    > static base_type & instance() {
    > static this_type meyers;
    > if( this_type::m_de stroyed ) {
    > new( &meyers ) this_type;
    > atexit( this_type::do_a texit );
    > }
    > return meyers;
    > }
    > private:
    > typedef phoenix<base_ty pe,context_type > this_type;
    > static bool m_destroyed;
    > phoenix() { m_destroyed = false; }
    > ~phoenix() { m_destroyed = true; }
    > static void do_atexit() {
    > if( m_destroyed ) return;
    > static_cast<thi s_type SPMamp;>(instan ce()).~phoenix( );
    > }
    > };
    > template <typename T, typename C> bool phoenix<T,C>::m _destroyed = false;
    >
    > This code is complete for purposes of the questions posed here, but the[/color]
    code[color=blue]
    > at http://s11n.net/misccode/phoenix.h is "more complete", with docs,
    > comments, one additional (optional) template parameter and debugging code.
    >
    > Regarding the implementation, i have these questions:
    >
    > - What happens when BaseType has a non-virtual destructor? We never use
    > delete(), relying on static destruction instead, so i think this is safe.[/color]
    i[color=blue]
    > have successfully used this class with, e.g., std::map<> as BaseType, but
    > maybe i just have a remarkably accomodating C++ platform.
    >
    > - Is it possible that m_destroyed gets destroyed at a point such that the
    > above usages of it becomes invalid? If so, is there a way to phoenix that
    > bool, so to speak?
    >
    >
    > Any insights on these points would be greatly appreciated.
    >
    >
    > --
    > ----- stephan beal
    > http://s11n.net/
    > Registered Linux User #71917 http://counter.li.org
    > I speak for myself, not my employer. Contents may
    > be hot. Slippery when wet. Reading disclaimers makes
    > you go blind. Writing them is worse. You have been Warned.
    >[/color]


    Comment

    • Martijn Lievaart

      #3
      Re: Phoenix Singletons

      On Tue, 30 Dec 2003 09:16:12 +0000, Nick Hounsome wrote:

      [ Please don't toppost. Thx, M4 ]
      [color=blue]
      > It's undefined behaviour.
      > You obviously know that it is undefined behaviour.
      > Getting someone on this newsgroup to say it's OK wont make it so.[/color]

      Where is the UB? Why do you think he knows this?

      M4

      Comment

      • Victor Bazarov

        #4
        Re: Phoenix Singletons

        "stephan beal" <stephan@s11n.n et> wrote...[color=blue]
        > [...]
        > template < typename BaseType, typename ContextType = BaseType >
        > class phoenix : public BaseType {
        > public:
        > typedef ContextType context_type;
        > typedef BaseType base_type;
        > static base_type & instance() {
        > static this_type meyers;
        > if( this_type::m_de stroyed ) {
        > new( &meyers ) this_type;
        > atexit( this_type::do_a texit );
        > }
        > return meyers;
        > }
        > private:
        > typedef phoenix<base_ty pe,context_type > this_type;
        > static bool m_destroyed;
        > phoenix() { m_destroyed = false; }
        > ~phoenix() { m_destroyed = true; }
        > static void do_atexit() {
        > if( m_destroyed ) return;
        > static_cast<thi s_type SPMamp;>(instan ce()).~phoenix( );
        > }
        > };
        > template <typename T, typename C> bool phoenix<T,C>::m _destroyed = false;[/color]

        I have only a few questions: have you checked what happens when you call
        'atexit' to register the function that is being executed at that moment?
        I mean, the rest of it is working allegedly, but have you tried using
        'exit' in your program? Does it actually exit or does it fall into
        an endless loop?

        Have you checked whether the number of d-tor calls matches the number of
        c-tor calls?

        In your 'instance' function, if the object has been destroyed, you never
        set the flag back to 'false'. Is that intentional?


        Comment

        • stephan beal

          #5
          Re: Phoenix Singletons

          Victor Bazarov wrote:[color=blue]
          > I have only a few questions: have you checked what happens when you call[/color]

          Hi, Victor! i appologize for the delayed response: i was out for the
          holidays longer than i expected.
          [color=blue]
          > 'atexit' to register the function that is being executed at that moment?
          > I mean, the rest of it is working allegedly, but have you tried using
          > 'exit' in your program? Does it actually exit or does it fall into
          > an endless loop?[/color]

          That's a good question. Now that i think about it, i never call exit()
          manually - i return from main() instead. i'll give that a try.
          [color=blue]
          > Have you checked whether the number of d-tor calls matches the number of
          > c-tor calls?[/color]

          Yes, from what i've seen they do match.
          [color=blue]
          > In your 'instance' function, if the object has been destroyed, you never
          > set the flag back to 'false'. Is that intentional?[/color]

          That is set via the phoenix's ctor and dtor, so it will be togged to false
          when the object is initially created or any time that the object is
          phoenixed, and to true when the object is destroyed normally or destroyed
          via do_atexit().


          --
          ----- stephan beal

          Registered Linux User #71917 http://counter.li.org
          I speak for myself, not my employer. Contents may
          be hot. Slippery when wet. Reading disclaimers makes
          you go blind. Writing them is worse. You have been Warned.

          Comment

          • stephan beal

            #6
            Re: Phoenix Singletons

            Nick Hounsome wrote:
            [color=blue]
            > It's undefined behaviour.
            > You obviously know that it is undefined behaviour.
            > Getting someone on this newsgroup to say it's OK wont make it so.[/color]

            You'r mistaken: what i KNOW is that deleting a POINTER to a derived type
            when the parent has a non-virtual dtor is undefined behaviour. What i DON'T
            know is what happens for NON-POINTERS which are never delete()ed.

            --
            ----- stephan beal

            Registered Linux User #71917 http://counter.li.org
            I speak for myself, not my employer. Contents may
            be hot. Slippery when wet. Reading disclaimers makes
            you go blind. Writing them is worse. You have been Warned.

            Comment

            Working...