Jump to content
  • Advertisement
Sign in to follow this  
erichardson

Singleton woes

This topic is 4973 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

In order to get to the problem I will have to "set the scene" a little. Please bear with me... I have the following Singleton template class which resides in a static library (.lib).
template <typename T>
class CSingleton
{
protected:
	static T* m_Singleton;

public:
	// Constructor
	CSingleton()
	{
		assert(!m_Singleton);
#if defined( _MSC_VER ) && _MSC_VER < 1200
		int Offset = (int)(T*)1 - (int)(CSingleton<T>*)(T*)1;
		m_Singleton = (T*)((int)this + Offset);
#else
		m_Singleton = static_cast<T*>(this);
#endif
	}

	// Destructor
	~CSingleton()
	{
		assert(m_Singleton);
		m_Singleton = NULL;
	}

	static T& GetSingleton()
	{
		assert(m_Singleton);
		return *m_Singleton;
	}

	static T* GetSingletonPtr()
	{
		assert(m_Singleton);
		return m_Singleton;
	}
};

template <typename T> T* CSingleton <T>::m_Singleton = NULL;

In this static library I also have a CLogger class which inherits from this Singleton class. In my application (.exe) I link to this .lib and instantiate a CLogger class. The .exe also links to a .dll at runtime and this dll contains the following code which is causing me the problem...
CLogger::GetSingleton()->Log("D3D9Graphics.dll", "CD3D9Graphics", 
			"Init", "Failed to create Direct3DDevice9");

The problem is that the previous bit of code causes an assertion because the m_Singleton member is null. However, in the .exe, I have the following bit of code which does work as the log is created and written to...
m_Logger.GetSingleton().CreateLog("log.txt");

Can anyone explain to me why this is happening and how I might be able to solve this problem?

Share this post


Link to post
Share on other sites
Advertisement
I think...

If you use the static method without initiating m_Singleton first, it will always be null. Therefore, what you should do is:


static T& GetSingleton(){
if(!m_Singleton){
m_Singleton = new T;
}}
return m_Singleton;



I suspect that if you create m_Logger then call CLogger statically, it would work fine, because m_Singleton would have been created. But because CLogger is called first, m_Singleton is null.

Something like that should work.

-visage

Share this post


Link to post
Share on other sites
Templates can't reside in binary libraries. Only template instances, like CSingleton<Foo>, where Foo is a real type, can. (So, in fact, CLogger should be fine).

Singletons are generally much more trouble than they are worth.

Have you checked that your offset trickery is legit?

Where's the code for CreateLog() and Log() ?

Why does one use . and the other ->, when GetSingleton() returns a reference?

What is m_Logger? What is its relation with CLogger?

Where is your CLogger instance created?

Share this post


Link to post
Share on other sites
Well, maybe he could just overload GetSingleton in CLogger? Something like:


static CLogger& GetSingleton(){
if(!m_Singleton)
m_Singleton = new CLogger;
return m_Singleton;
}


This should work, right? Or maybe this snow day has just made my mind lazy.

You seem to be correcting me left and right here, Fruny ;)

[Edited by - visage on January 6, 2005 4:03:49 PM]

Share this post


Link to post
Share on other sites
What does the header for CLogger look like? You might have to override the singleton retrieval method as such:

static CLogger& getSingleton(void);

[Edit] Oops, didn't refresh the page before replying and didn't see the prior response.

Share this post


Link to post
Share on other sites
Quote:

What does the header for CLogger look like?



class CLogger : public CSingleton<CLogger>
{
private:
std::ofstream m_Out;

public:
// Constructor
CLogger();
CLogger(String szName);

// Destructor
~CLogger();

// Creates a new log
void CreateLog(String szName);

// Logs a message
void Log(String szModule, String szClass, String szFunction, String szMsg);
};



Quote:

Have you checked that your offset trickery is legit?


I plead guilty. Although I don't follow this little bit of code, I have debugged the app and the m_Singleton variable gets initialised to something other than 0x000000 so I figured it would be working...

Quote:

Where's the code for CreateLog() and Log() ?



void CLogger::Log(String szModule, String szClass, String szFunction, String szMsg)
{
SYSTEMTIME dt;
GetSystemTime(&dt);

m_Out << dt.wDay << "/" << dt.wMonth << "/" << dt.wYear << " " <<
dt.wHour << ":" << dt.wMinute << ":" << dt.wSecond << " (" <<
szModule << ": " << szClass << ": " << szFunction << ") " <<
szMsg << std::endl;
}

void CLogger::CreateLog(String szName)
{
m_Out.open(szName.c_str(), std::ios::out);

SYSTEMTIME dt;
GetSystemTime(&dt);

m_Out << dt.wDay << "/" << dt.wMonth << "/" << dt.wYear << " " <<
dt.wHour << ":" << dt.wMinute << ":" << dt.wSecond <<
" Log created" << std::endl;
}



Quote:

Why does one use . and the other ->, when GetSingleton() returns a reference?


That's a typo on my part while I was making this post [lol]

Quote:

What is m_Logger? What is its relation with CLogger?

Where is your CLogger instance created?


m_Logger is just what I called an instance of CLogger. m_ because it is a member variable of my application class. It is created when the application is started.

Quote:

Singletons are generally much more trouble than they are worth.


I'm starting to agree...[smile]



Share this post


Link to post
Share on other sites
If you include a getSingleton method in the CLogger class it is not overriding but hiding the Singleton's method since you can not override static methods. In this case it may not be too bad but something to look out for.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!