C++
  Home arrow C++ arrow Page 4 - C++ In Theory: The Singleton Pattern, Part...
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
C++

C++ In Theory: The Singleton Pattern, Part 2
By: J. Nakamura
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 4 stars4 stars4 stars4 stars4 stars / 26
    2005-01-25

    Table of Contents:
  • C++ In Theory: The Singleton Pattern, Part 2
  • Singleton Generalization
  • Testing Our Generic Implementation
  • Singletons are not for Simpletons

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    C++ In Theory: The Singleton Pattern, Part 2 - Singletons are not for Simpletons


    (Page 4 of 4 )

    While the implementation looks deceptively simple and stable, it harbors a pretty nasty problem: the sequence of static object destruction is not given when an application is being terminated. Imagine two singletons A and B using a logging class L (which is the singleton from the previous article), and after A has used the log in a regular way, the other singleton B causes the application to terminate.

    The construction sequence might very well be A – L – C when C fails and terminates the application. So C is destructed first, followed by the Log singleton L, and finally singleton A is destroyed. There is no reason why A won’t attempt to write to the Log while it is being destroyed (destructors are a good location to dump the internal state of an object to the log). But the Log instance was just destroyed! So LOG::Instance().Write() will at best yield an exception or at worst cause your application to terminate the hard way!

    The book Modern C++ Design [Alexandrescu] describes this problem in detail and demonstrates multiple solutions, from using the Phoenix Singleton to revive dead singletons, to using Policy template classes to control a Singleton's lifetime. The book is very advanced, very enjoyable and very useful. I have chosen to demonstrate an easy way out to you for now. We will implement a policy option to create either a Meyers Singleton or a Gamma Singleton and leave it at that for now.

    If you have read the previous article, you will know that the Meyers Singleton is an implementation that prevents memory leakage. The Gamma Singleton, on the other hand, doesn’t clean up after itself and this comes in handy with our destruction sequence problem. The best way to guarantee our singleton will remain alive to the very end is by simply not destroying it!

    Please note that we will depend on the operating system to clean up memory for us, and we have to be very careful not to create a resource leak! Take a look at the Loki library [Alexandrescu] to find out what the complete solution is when the ones I have given you won’t suffice anymore (or when you are curious of course). It will be very trivial to replace these singletons with the Loki ones.

    Our singleton needs two different methods of creation. If we externalize these creation methods from the singleton class and provide one of them as a template parameter, the singleton class has become configurable as far as its creation is concerned. This is what policies [Alexandrescu] are all about.

    I have constructed a CreateGamma and a CreateMeyers class to demonstrate this concept:

    // singleton.h
    #ifndef __SINGLETON_H
    #define __SINGLETON_H

    //
    // for a definite implementation of the singleton check out
    //
    http://sourceforge.net/projects/loki-lib/
    //
    // or the book “Modern C++ Design” by A.Alexandrescu
    //

    // This is how a Gamma Singleton would instantiate its object.
    template <class T> struct CreateGamma {
      static T* Create() { return new T; }
    };

    // This is how a Meyers Singleton would instantiate its object.
    template <class T> struct CreateMeyers {
      static T* Create() {
        static T _instance;
        return &_instance;
      }
    };

    // This Singleton class accepts different creation policies.
    template <class T, template<class> class CreationPolicy=CreateMeyers>
    class Singleton {
    public:
      static T& Instance() {
        if (!m_pInstance)
          m_pInstance=CreationPolicy<T>::Create();
        return *m_pInstance;
    }

    private:
      Singleton();          // ctor hidden
      ~Singleton();          // dtor hidden
      Singleton(Singleton const&);    // copy ctor hidden
      Singleton& operator=(Singleton const&);  // assign op hidden

      static T* m_pInstance;
    };

    template <class T, template<class> class C>
    T* Singleton<T,C>::m_pInstance=0;

    #endif // __SINGLETON_H
    // eof

    Now we can add the following code to our test in main.cpp:

    typedef Singleton<MyClass, CreateGamma> MyClassLeaking;

    void test3()
    {
    int val=MyClassLeaking::Instance().bar();
    MyClassLeaking::Instance().foo(++val);
    (void)MyClassLeaking::Instance().bar();
    }

    // in main()
      (void)printf(“\n*** using leaking singleton ***\n”);
      MyLeakingSingleton::Instance().foo(0x0100);
      (void)printf(“*** test3 ***\n”);
      test3();
      (void)printf(“*** test3 ***\n”);
      test3();

    And see that it yields the desired leakage:

    *** using leaking singleton ***
    MyClass #4 constructed.      #here our singleton is constructed
    MyClass4::foo(0x00000100) called.
    *** test3 ***
    MyClass4::bar() called.
    ... m_Value is: 0x00000100.
    MyClass4::foo(0x00000101) called.
    MyClass4::bar() called.
    ... m_Value is: 0x00000101.
    *** test3 ***          #it lives fine across all calls
    MyClass4::bar() called.
    ... m_Value is: 0x00000101.
    MyClass4::foo(0x00000102) called.
    MyClass4::bar() called.
    ... m_Value is: 0x00000102.

    --- DONE ---
    MyClass #3 destructed.      #the Meyers Singleton is destroyed
                #and our Gamma Singleton is still alive!

    At first I thought it would be easy to describe the singleton, until I remembered the troubles I’ve had with construction and destruction sequences of multiple interdependent singletons. Hopefully I have been able to shed some insight into the usage of this "simple" design pattern.

    References

    [Gamma] Design Patterns: E.Gamma, R.Helm, R.Johnson and J.Vlissides.
    [Alexandrescu] Modern C++ Design: A.Alexandrescu.
    [Meyers] More Effective C++: S.Meyers.


    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

       · Very nice. But one question from dummy-programmer: what, if my class has a...
       · If you want your singleton to use parameters in its construction, for example...
       · A good introduction, but for the serious more advanced programmer, you can introduce...
     

    C++ ARTICLES

    - Paths and Files
    - Directories in C++
    - Focusing on C++ Files
    - Const Correctness in C++
    - Manipulating Streams and Files with C++
    - Streams and Files
    - Multiplying Large Numbers with Karatsuba`s A...
    - Large Numbers
    - Dijkstra`s Shunting Algorithm with STL and C...
    - Brief Introduction to the STL Containers
    - The Standard Template Library
    - Templates in C++
    - C++ Programmer Alerts
    - C++ Programming Tips
    - First Steps in (C) Programming, conclusion






    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 5 hosted by Hostway
    Stay green...Green IT