Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   singleton question (http://www.velocityreviews.com/forums/t744126-singleton-question.html)

kathy 02-24-2011 03:23 PM

singleton question
 
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 02-24-2011 04:17 PM

Re: singleton question
 
On Feb 24, 9:45*am, Leigh Johnston <le...@i42.co.uk> 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 :(

Victor Bogado 03-02-2011 03:25 PM

Re: singleton question
 
On Feb 24, 12:23*pm, kathy <yqin...@yahoo.com> 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 03-02-2011 05:28 PM

Re: singleton question
 
On Mar 2, 12:31*pm, Leigh Johnston <le...@i42.co.uk> wrote:
> On 02/03/2011 15:25, Victor Bogado wrote:
>
> > On Feb 24, 12:23 pm, kathy<yqin...@yahoo.com> *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 03-02-2011 05:33 PM

Re: singleton question
 
On Mar 2, 2:28*pm, Victor Bogado <bog...@gmail.com> wrote:
> On Mar 2, 12:31*pm, Leigh Johnston <le...@i42.co.uk> wrote:
>
>
>
>
>
>
>
>
>
> > On 02/03/2011 15:25, Victor Bogado wrote:

>
> > > On Feb 24, 12:23 pm, kathy<yqin...@yahoo.com> *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

James Kanze 03-02-2011 07:21 PM

Re: singleton question
 
On Mar 2, 5:34 pm, Leigh Johnston <le...@i42.co.uk> wrote:
> On 02/03/2011 17:33, Victor Bogado wrote:
> > On Mar 2, 2:28 pm, Victor Bogado<bog...@gmail.com> wrote:
> >> On Mar 2, 12:31 pm, Leigh Johnston<le...@i42.co.uk> wrote:


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


> >>>> On Feb 24, 12:23 pm, kathy<yqin...@yahoo.com> 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

Andy Venikov 03-03-2011 03:50 PM

Re: singleton question
 
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.


All times are GMT. The time now is 11:19 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.