Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. The Singleton Pattern
QtWS25 Last Chance

The Singleton Pattern

Scheduled Pinned Locked Moved C++ Gurus
15 Posts 8 Posters 18.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    cazador7907
    wrote on last edited by
    #1

    In doing research on the web about implementing the single pattern in C++, I noticed something odd in the different code samples and articles that I've been reading and I'm hoping that the folks here can enlighten me. The code snippet below, the singleton is destroyed in the drop function. My question is why is the object variable set to 0 after it's destroyed?

    @
    static MathUtility::Drop()
    {
    static QMutex mutex;

    mutex.lock();
    delete m_MathUtility;
    m_MathUtility = 0;
    mutex.unlock();
    

    }
    @

    Laurence -

    1 Reply Last reply
    0
    • G Offline
      G Offline
      giesbert
      wrote on last edited by
      #2

      Hi cazador7907,

      it's good practice to set a pointer to 0 if it gets invalid. Otherwise your pointer adresses some meory that is already freed, which means everything can happen, also an airplanecrash :-)

      The more interesting point is the mutex there, it only secures the deletionof the object, nothing else. What about a createInstance? What about accessing methods, that access exactly the same time that drop is called? That will lead to undefined behavior...

      Nokia Certified Qt Specialist.
      Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

      1 Reply Last reply
      0
      • C Offline
        C Offline
        cazador7907
        wrote on last edited by
        #3

        If the different examples that I have seen the common pattern that I'm finding is below. If I'm reading (and understanding the code correctly). A check is performed to determine if the object exists. If it doesn't the mutex object is set during the process of creating the object to prevent simultaneous creation calls. I've put an example of the code below.

        @
        MathUtility* MathUtility::Mathematics()
        {
        static QMutex mutex;
        if( !m_MathUtility )
        {
        mutex.lock();

            if( !m_MathUtility )
                m_MathUtility = new MathUtility;
        
            mutex.unlock();
        }
        
        //return the created instance
        return m_MathUtility;
        

        }
        @

        Laurence -

        1 Reply Last reply
        0
        • T Offline
          T Offline
          tony
          wrote on last edited by
          #4

          Well,

          if you don't need to destroy the singleton at run-time, I prefer this technique to implement singleton pattern:

          @
          class Singleton
          {

          Singleton();
          Singleton(const Singleton &);

          public:
          static Singleton &get();
          };

          Singleton &Singleton::get()
          {
          static Singleton obj;

          return obj;
          }
          @

          The singleton will be created the first time you call "get".

          1 Reply Last reply
          0
          • G Offline
            G Offline
            giesbert
            wrote on last edited by
            #5

            That's also a valid pattern, yes.

            But sometimes, it makes sense to destroy a singleton, depending on the app and the singleton. But I would use one mutex for create and destroy, so these two can't mix up

            otherwise thread one destroys, while thread 2 creates. What will happen if the if( !m_MathUtility ) line is executed befor3e the current m_MathUtility = 0 statement?

            Nokia Certified Qt Specialist.
            Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

            1 Reply Last reply
            0
            • C Offline
              C Offline
              cazador7907
              wrote on last edited by
              #6

              I'm think that I'm tracking with you. If the mutex is made a member variable of the object then this won't happen, yes?

              Laurence -

              1 Reply Last reply
              0
              • G Offline
                G Offline
                goetz
                wrote on last edited by
                #7

                The mutex should be a static member of the class.

                http://www.catb.org/~esr/faqs/smart-questions.html

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  giesbert
                  wrote on last edited by
                  #8

                  If it would be a non static member, you could only access it after creationm of the object, so two creations at tzhe same time could happen.

                  Make it, like Volker said, a static member of the class, or a static object in the cpp file, both will work.

                  Nokia Certified Qt Specialist.
                  Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                  1 Reply Last reply
                  0
                  • B Offline
                    B Offline
                    baysmith
                    wrote on last edited by
                    #9

                    For the double-checked locking pattern to be thread-safe, in addition to using a mutex, the read and write to m_MathUtility must be atomic. [1]

                    @
                    class MathUtility
                    {
                    static QAtomicPointer<MathUtility> m_MathUtility;
                    static QMutex mutex;
                    public:
                    static MathUtility* Mathematics();
                    static void Drop();
                    };
                    @

                    @
                    QAtomicPointer<MathUtility> MathUtility::m_MathUtility;
                    QMutex MathUtility::mutex;

                    MathUtility* MathUtility::Mathematics()
                    {
                    if( !m_MathUtility )
                    {
                    mutex.lock();
                    if( !m_MathUtility )
                    m_MathUtility = new MathUtility;
                    mutex.unlock();
                    }
                    return m_MathUtility;
                    }

                    void MathUtility::Drop()
                    {
                    mutex.lock();
                    delete m_MathUtility;
                    m_MathUtility = 0;
                    mutex.unlock();
                    }
                    @

                    [1] http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf

                    Nokia Certified Qt Specialist.

                    1 Reply Last reply
                    0
                    • C Offline
                      C Offline
                      cazador7907
                      wrote on last edited by
                      #10

                      Very interesting reading on the concept (and perils) of the singleton pattern! Thanks for all of the suggestions and advice. Until today, I had never heard about something called QAtomicPointer.

                      Laurence -

                      1 Reply Last reply
                      0
                      • frankcyblogic.deF Offline
                        frankcyblogic.deF Offline
                        frankcyblogic.de
                        wrote on last edited by
                        #11

                        Local statics to implement singletons are cool, but I hate the fact that modern compilers throw in implicit (dead-)locking code. So I tend to disable that and use "my own local static allocator":https://github.com/unclefrank/libftl/blob/master/ftl/LocalStatic.hpp instead. Just my two cents.

                        1 Reply Last reply
                        0
                        • B Offline
                          B Offline
                          baysmith
                          wrote on last edited by
                          #12

                          With the next C++ standard, local statics will have thread-safe initialization. However, the above will still be needed if the ability to destruct the singleton is required.

                          Nokia Certified Qt Specialist.

                          1 Reply Last reply
                          0
                          • Z Offline
                            Z Offline
                            ZapB
                            wrote on last edited by
                            #13

                            Also, it is worth while to use QMutexLocker when dealing with mutexes. This saves having to catch exceptions all over the place and ensuring that your mutex is properly unlocked. The QMutexLocker destructor does this for you even if an exception is thrown as the stack is unwound.

                            Nokia Certified Qt Specialist
                            Interested in hearing about Qt related work

                            1 Reply Last reply
                            0
                            • C Offline
                              C Offline
                              cyberandy
                              wrote on last edited by
                              #14

                              Back to your originally question of assigning 0 to the deallocated pointer.
                              It's only an implicit convention that NULL pointers are not pointing to allocated memory.
                              I hope this is the case on all platforms now and forever!

                              Andreas Metzner
                              Dipl.-Inform. Univ.

                              1 Reply Last reply
                              0
                              • G Offline
                                G Offline
                                goetz
                                wrote on last edited by
                                #15

                                See "C++ FAQ 16.8":http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.8:

                                bq. C++ language guarantees that delete p will do nothing if p is equal to NULL. Since you might get the test backwards, and since most testing methodologies force you to explicitly test every branch point, you should not put in the redundant if test.

                                It is guaranteed by the standard that assigning 0 (digit zero) to a pointer in the source code is equivalent to assigning null to the pointer (the same holds for comparison with ==).

                                This is independent of the internal representation of a null pointer! The latter can be different from the numeric value zero, so memsetting all bits of a pointer to zero can lead to something different than a null pointer!

                                http://www.catb.org/~esr/faqs/smart-questions.html

                                1 Reply Last reply
                                0

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved