singleton question

Discussion in 'C++' started by kathy, Feb 24, 2011.

  1. kathy

    kathy Guest

    I try to implement the Singleton for my Driver. The code piece:

    /////////////////////////
    MySingleton.h
    /////////////////////////
    template <class T> class CSingleton
    {
    public:
    static T* GetInstance();

    protected:
    CSingleton();
    ~CSingleton();

    private:
    CSingleton(CSingleton const&);
    CSingleton& operator=(CSingleton const&);
    static T* m_pInstance;
    };

    /////////////////////////
    MySingleton.cpp
    /////////////////////////

    #include "StdAfx.h"
    #include "MySingleton.h"

    template <class T> T* CSingleton<T>::m_pInstance=NULL;
    template <class T> T* CSingleton<T>::GetInstance()
    {
    if(!m_pInstance)
    m_pInstance = new T;

    assert(m_pInstance !=NULL);

    return m_pInstance;
    }

    /////////////////////////
    Driver.h
    /////////////////////////

    class CDriver
    {
    public:
    CDriver(void);
    ~CDriver(void);

    int GetData();

    private:
    int m_nData;
    };

    /////////////////////////
    Driver.cpp
    /////////////////////////

    #include "StdAfx.h"
    #include "Driver.h"


    CDriver::CDriver(void):
    m_nData(100)
    {
    }


    CDriver::~CDriver(void)
    {
    }

    int CDriver::GetData()
    {
    return m_nData;
    }

    In my MFC dialog button routine:

    void CMyDlg::OnBnClickedButtonSingleton()
    {
    int n = 1;
    CDriver *pDriver = CSingleton<CDriver>::GetInstance();
    n = pDriver->GetData();
    }

    When I try to build it in studio 2010, I got link error:

    MyDlg.obj : error LNK2019: unresolved external symbol "public: static
    class CDriver * __cdecl CSingleton<class
    CDriver>::GetInstance(void)" (?GetInstance@?
    $CSingleton@VCDriver@@@@SAPAVCDriver@@XZ) referenced in function
    "public: void __thiscall
    CBoostDlg::OnBnClickedButtonSingleton(void)" (?
    OnBnClickedButtonSingleton@CBoostDlg@@QAEXXZ)
    C:\Temp\Studio 2010\TestDlg\Debug\Test.exe : fatal error LNK1120: 1
    unresolved externals

    What is wrong?
    kathy, Feb 24, 2011
    #1
    1. Advertising

  2. kathy

    kathy Guest

    On Feb 24, 9:45 am, Leigh Johnston <> wrote:
    > On 24/02/2011 15:23, kathy wrote:
    >
    >
    >
    >
    >
    > > I try to implement the Singleton for my Driver. The code piece:

    >
    > > /////////////////////////
    > > MySingleton.h
    > > /////////////////////////
    > > template<class T>  class CSingleton
    > > {
    > > public:
    > >    static T* GetInstance();

    >
    > > protected:
    > >    CSingleton();
    > >    ~CSingleton();

    >
    > > private:
    > >    CSingleton(CSingleton const&);
    > >    CSingleton&  operator=(CSingleton const&);
    > >    static T* m_pInstance;
    > > };

    >
    > > /////////////////////////
    > > MySingleton.cpp
    > > /////////////////////////

    >
    > > #include "StdAfx.h"
    > > #include "MySingleton.h"

    >
    > > template<class T>  T* CSingleton<T>::m_pInstance=NULL;
    > > template<class T>  T* CSingleton<T>::GetInstance()
    > > {
    > >    if(!m_pInstance)
    > >    m_pInstance = new T;

    >
    > >    assert(m_pInstance !=NULL);

    >
    > >    return m_pInstance;
    > > }

    >
    > > /////////////////////////
    > > Driver.h
    > > /////////////////////////

    >
    > > class CDriver
    > > {
    > > public:
    > >    CDriver(void);
    > >    ~CDriver(void);

    >
    > >    int GetData();

    >
    > > private:
    > >    int m_nData;
    > > };

    >
    > > /////////////////////////
    > > Driver.cpp
    > > /////////////////////////

    >
    > > #include "StdAfx.h"
    > > #include "Driver.h"

    >
    > > CDriver::CDriver(void):
    > >    m_nData(100)
    > > {
    > > }

    >
    > > CDriver::~CDriver(void)
    > > {
    > > }

    >
    > > int CDriver::GetData()
    > > {
    > >    return m_nData;
    > > }

    >
    > > In my MFC dialog button routine:

    >
    > > void CMyDlg::OnBnClickedButtonSingleton()
    > > {
    > >    int n = 1;
    > >    CDriver *pDriver = CSingleton<CDriver>::GetInstance();
    > >    n = pDriver->GetData();
    > > }

    >
    > > When I try to build it in studio 2010, I got link error:

    >
    > > MyDlg.obj : error LNK2019: unresolved external symbol "public: static
    > > class CDriver * __cdecl CSingleton<class
    > > CDriver>::GetInstance(void)" (?GetInstance@?
    > > $CSingleton@VCDriver@@@@SAPAVCDriver@@XZ) referenced in function
    > > "public: void __thiscall
    > > CBoostDlg::OnBnClickedButtonSingleton(void)" (?
    > > OnBnClickedButtonSingleton@CBoostDlg@@QAEXXZ)
    > > C:\Temp\Studio 2010\TestDlg\Debug\Test.exe : fatal error LNK1120: 1
    > > unresolved externals

    >
    > > What is wrong?

    >
    > Move the code in MySingleton.cpp into MySingleton.h and delete
    > MySingleton.cpp that should fix it.
    >
    > By having template code in a different TU you are not instantiating it.
    >
    > /Leigh- Hide quoted text -
    >
    > - Show quoted text -


    Thank you. I forgot it :(
    kathy, Feb 24, 2011
    #2
    1. Advertising

  3. On Feb 24, 12:23 pm, kathy <> wrote:
    > ...
    >
    > template <class T> T* CSingleton<T>::m_pInstance=NULL;
    > template <class T> T* CSingleton<T>::GetInstance()
    > {
    >   if(!m_pInstance)
    >         m_pInstance = new T;


    Also This is not thread safe, you could have a race condition that
    would end up with 2 instances. The best solution is to use the
    instance as a static local in the instance method. The standard says
    that it will be instantiated before the first call.

    > ...
    Victor Bogado, Mar 2, 2011
    #3
  4. On Mar 2, 12:31 pm, Leigh Johnston <> wrote:
    > On 02/03/2011 15:25, Victor Bogado wrote:
    >
    > > On Feb 24, 12:23 pm, kathy<>  wrote:
    > >> ...

    >
    > >> template<class T>  T* CSingleton<T>::m_pInstance=NULL;
    > >> template<class T>  T* CSingleton<T>::GetInstance()
    > >> {
    > >>    if(!m_pInstance)
    > >>          m_pInstance = new T;

    >
    > > Also This is not thread safe, you could have a race condition that
    > > would end up with 2 instances. The best solution is to use the
    > > instance as a static local in the instance method. The standard says
    > > that it will be instantiated before the first call.

    >
    > No; such a static will be instantiated *during* the first call however
    > you still have a race condition with a local static in a multi-threaded
    > situation.
    >
    > /Leigh


    This would have a race condition? I was under the impression that the
    instantiation in that case would be atomic, but I never read the
    standard myself, so I could be wrong :p.

    static SingletonType& SingletonType::instance()
    {
    SingletonType instance;

    return instance;
    }
    Victor Bogado, Mar 2, 2011
    #4
  5. On Mar 2, 2:28 pm, Victor Bogado <> wrote:
    > On Mar 2, 12:31 pm, Leigh Johnston <> wrote:
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > On 02/03/2011 15:25, Victor Bogado wrote:

    >
    > > > On Feb 24, 12:23 pm, kathy<>  wrote:
    > > >> ...

    >
    > > >> template<class T>  T* CSingleton<T>::m_pInstance=NULL;
    > > >> template<class T>  T* CSingleton<T>::GetInstance()
    > > >> {
    > > >>    if(!m_pInstance)
    > > >>          m_pInstance = new T;

    >
    > > > Also This is not thread safe, you could have a race condition that
    > > > would end up with 2 instances. The best solution is to use the
    > > > instance as a static local in the instance method. The standard says
    > > > that it will be instantiated before the first call.

    >
    > > No; such a static will be instantiated *during* the first call however
    > > you still have a race condition with a local static in a multi-threaded
    > > situation.

    >
    > > /Leigh

    >
    > This would have a race condition? I was under the impression that the
    > instantiation in that case would be atomic, but I never read the
    > standard myself, so I could be wrong :p.
    >


    the code should be :

    static SingletonType& SingletonType::instance()
    {
        static SingletonType instance;
        return instance;
    }

    :p
    Victor Bogado, Mar 2, 2011
    #5
  6. kathy

    James Kanze Guest

    On Mar 2, 5:34 pm, Leigh Johnston <> wrote:
    > On 02/03/2011 17:33, Victor Bogado wrote:
    > > On Mar 2, 2:28 pm, Victor Bogado<> wrote:
    > >> On Mar 2, 12:31 pm, Leigh Johnston<> wrote:


    > >>> On 02/03/2011 15:25, Victor Bogado wrote:


    > >>>> On Feb 24, 12:23 pm, kathy<> wrote:
    > >>>>> ...


    > >>>>> template<class T> T* CSingleton<T>::m_pInstance=NULL;
    > >>>>> template<class T> T* CSingleton<T>::GetInstance()
    > >>>>> {
    > >>>>> if(!m_pInstance)
    > >>>>> m_pInstance = new T;


    > >>>> Also This is not thread safe, you could have a race condition that
    > >>>> would end up with 2 instances. The best solution is to use the
    > >>>> instance as a static local in the instance method. The standard says
    > >>>> that it will be instantiated before the first call.


    > >>> No; such a static will be instantiated *during* the first call however
    > >>> you still have a race condition with a local static in a multi-threaded
    > >>> situation.


    > >> This would have a race condition? I was under the impression that the
    > >> instantiation in that case would be atomic, but I never read the
    > >> standard myself, so I could be wrong :p.


    > > the code should be :


    > > static SingletonType& SingletonType::instance()
    > > {
    > > static SingletonType instance;
    > > return instance;
    > > }


    > > :p


    > Not thread-safe. :p


    That depends. According to the draft C++0x: "If control enters
    the declaration [of a local static variable] concurrently while
    the object variable is being initialized, the concurrent
    execution shall wait for completion of the initialization." Pre
    C++0x, anything involving threads was defined by the
    implementation (undefined behavior according to the standard,
    but an implementation is free to define undefined behavior, and
    both Posix and Windows do). In this case, g++ has always
    behaved as C++0x will require, or at least, it has officially
    guaranteed it did, since the first version which supported
    threading at all (3.0).

    --
    James Kanze
    James Kanze, Mar 2, 2011
    #6
  7. kathy

    Andy Venikov Guest

    On 03/02/2011 02:21 PM, James Kanze wrote:
    <snip>

    >
    >> Not thread-safe. :p

    >
    > That depends. According to the draft C++0x: "If control enters
    > the declaration [of a local static variable] concurrently while
    > the object variable is being initialized, the concurrent
    > execution shall wait for completion of the initialization." Pre
    > C++0x, anything involving threads was defined by the
    > implementation (undefined behavior according to the standard,
    > but an implementation is free to define undefined behavior, and
    > both Posix and Windows do). In this case, g++ has always
    > behaved as C++0x will require, or at least, it has officially
    > guaranteed it did, since the first version which supported
    > threading at all (3.0).


    Actually, thread-safe locals were introduced in 3.4. (They may have been
    back-patched to earlier versions, but they did not exist in the originals).

    But it looks like prior to 4.0 the logic was broken for non-POD types
    since the constructor would be called while holding a global lock and if
    the constructor contained another local static or was calling a function
    that contained a global static, the program would dead-lock since the
    global lock was not re-entrant.

    MSVC never tried to make static locals thread-safe. That is, prior to C++0x


    >
    > --
    > James Kanze


    Andy.
    Andy Venikov, Mar 3, 2011
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Proton Projects - Moin

    Singleton - Whether Cloneable overrides Singleton

    Proton Projects - Moin, Mar 26, 2007, in forum: Java
    Replies:
    4
    Views:
    3,222
    Proton Projects - Moin
    Mar 27, 2007
  2. Wilhelm
    Replies:
    1
    Views:
    158
  3. Trans
    Replies:
    12
    Views:
    269
    Robert Klemme
    Sep 14, 2007
  4. Paul McMahon
    Replies:
    3
    Views:
    198
    David A. Black
    Jun 9, 2008
  5. Charles Oliver Nutter

    Singleton methods without the singleton class

    Charles Oliver Nutter, Mar 15, 2010, in forum: Ruby
    Replies:
    4
    Views:
    198
    Charles Oliver Nutter
    Mar 22, 2010
Loading...

Share This Page