singleton question

K

kathy

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?
 
K

kathy

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 :(
 
V

Victor Bogado

...

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.
 
V

Victor Bogado

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;
}
 
V

Victor Bogado

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
 
J

James Kanze

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).
 
A

Andy Venikov

On 03/02/2011 02:21 PM, James Kanze wrote:
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


Andy.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top