![]() |
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? |
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 :( |
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. > ... |
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; } |
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 |
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 |
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 04:30 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.