Skip to main content
GameDev.net gamedev.net
🔒 Locked

Automatic Singleton question

Started by Eric Poitras Apr 12, 2005 at 1:08 PM 27 replies 4.2k views
Original Post
Eric Poitras
Eric Poitras
hey all I tried using the code from the article in the book Game Programming Gems 1 called "An Automatic Singleton Utility" but I seem to always get an assert message. I don't understand why I am because I'm following everything from the book. Does anyone know if there's an error in the code? btw the assert return is from this part of the code:

static T& GetSingleton( void )
   { assert(ms_Singleton); return (*ms_Singleton); }
any ideas?
All that is necessary for the triumph of evil is that good men do nothing. -Edmund Burke
y2kiah
y2kiah
you need to create an instance of the class before using it
Eric Poitras
Eric Poitras
what do you mean? like I made another class that looks like this

class cCore : public Singleton <cCore>{public:   //insert code here};#define g_cCore cCore::GetSingleton()


is that what you meant?
All that is necessary for the triumph of evil is that good men do nothing. -Edmund Burke
Drew_Benton
Drew_Benton
Quote:
Original post by y2kiah
you need to create an instance of the class before using it


Correct! If you look on page 39 at #2, it says that you must construct an instance of your class before you use it. It then tells you all the ways you could do that, to which all that matters is that you do indeed instantiate it.

So you would need to do something like: cCore::ms_Singleton = new cCore; *I think*. See if that works. That can go in your main function or somewhere so it is only called once.
Eric Poitras
Eric Poitras
sigh... ok look at the code above.. that's my class and I'm using the singleton template for it.

Now this line is like a macro:
#define g_cCore cCore::GetSingleton()

when I go to my main code I have something like this
int test = g_cCore.SomeFunctionThatReturnsSomething();

now when I call this function (lets say it's in my class) the program crashes and gives me an assertion failure. why?
All that is necessary for the triumph of evil is that good men do nothing. -Edmund Burke
Eric Poitras
Eric Poitras
Should I just post all the code I have? maybe it would make it easier... oh and btw I tried that line you gave me and all that did was give me a bunch of errors... maybe I should take a break... been trying to understand this since this morning...
All that is necessary for the triumph of evil is that good men do nothing. -Edmund Burke
mrbastard
mrbastard
I think you still haven't instanciated the class. The assert will throw a message if ms_singleton == null.

To be clear:

ms_singleton = new Singleton;

in this fragment I instanciate a new Singleton object, and set ms_singleton to point to it. Though as Singleton is a baseclass, you should actually instanciate an object of the concrete class you are using - cCore.

The singleton pattern ensures that there is only ever one instance (as you know), but you still need to create (eg assign memory for, call constructor of, etc) that instance somewhere in your code.
[size="1"]
JimPrice
JimPrice
Slightly not-answering-your-question, but:

have you looked at Enginuity part 2 - it's a very similar implementation, from what I remember. You might be able to find your missing link.

Alternatively, can I suggest the Loki library, available from here. Implementation is dead easy, just need to use something like the following code - and it handles a lot more issues than the code you're using.

#include <singleton.h>class SingletonWindowManager{public:// Some user functionsprivate:// These are all required by Loki to get proper singleton behaviour	SingletonWindowManager(void);	~SingletonWindowManager(void);	SingletonWindowManager(const SingletonWindowManager&);	SingletonWindowManager& operator=(const SingletonWindowManager&);	SingletonWindowManager* operator&(const SingletonWindowManager&);	friend Loki::CreateUsingNew<SingletonWindowManager>;};typedef Loki::SingletonHolder<SingletonWindowManager> WindowManager;


If you want you can now use a #define for WindowManager::Instance() in the same way as you have with your own code.

Hope this helps,
Jim.
Eric Poitras
Eric Poitras
ok here's my template:
#ifndef __SINGLETONTEMPLATE_H__#define __SINGLETONTEMPLATE_H__#include <cassert>template <typename T> class Singleton{	static T* ms_Singleton;	public:		Singleton( void )		{			assert( !ms_Singleton );			int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1;			ms_Singleton = (T*)((int)this + offset);		}		~Singleton( void )			{ assert(ms_Singleton); ms_Singleton = 0; }		static T& GetSingleton( void )			{ assert(ms_Singleton); return (*ms_Singleton); }		static T* GetSingletonPtr( void )			{ return (ms_Singleton); }};template <typename T> T* Singleton <T>::ms_Singleton = 0;#endif


now here's my class:
#ifndef __CORE_H__#define __CORE_H__#include "SingletonTemplate.h"#include <stdio.h>#include <stdlib.h>#include <conio.h>#include <curses.h>class cCore : public Singleton <cCore>{public:	int blah( void )	{		return 3;	}};#define g_cCore cCore::GetSingleton()#endif


and now in my main code:
int main(int argc, char *argv[]){    int i;   i = g_cCore.blah();   return 0;}
All that is necessary for the triumph of evil is that good men do nothing. -Edmund Burke
mrbastard
mrbastard
add this at the start of main:

Singleton::ms_singleton = new cCore;

or something to that effect.
[size="1"]
Eric Poitras
Eric Poitras
nope not working

c:\documents and settings\eric poitras\my documents\projects\wotrogue\main.cpp(3) : error C2039: 'ms_singleton' : is not a member of 'Singleton'
c:\documents and settings\eric poitras\my documents\projects\wotrogue\main.cpp(3) : error C2501: 'ms_singleton' : missing storage-class or type specifiers
c:\documents and settings\eric poitras\my documents\projects\wotrogue\main.cpp(3) : error C2440: 'initializing' : cannot convert from 'class cCore *' to 'int'
This conversion requires a reinterpret_cast, a C-style cast or function-style cast
All that is necessary for the triumph of evil is that good men do nothing. -Edmund Burke
mrbastard
mrbastard
try ms_Singleon (capital S on singleton)
[size="1"]
Drew_Benton
Drew_Benton
All you really need to do is something like: cCore c1; as a global variable and it will work. I just tried it out with your pasted code [smile] The idea is to instantiate the static varoiable with new memory, which can be done though a global variable or by specifically allocating new memory for it.
Eric Poitras
Eric Poitras
yeah I tried that but still nothing.... when I type

Singleton::

I only have access to
GetSingleton()
GetSingletonPtr()
~Singleton()
All that is necessary for the triumph of evil is that good men do nothing. -Edmund Burke
mrbastard
mrbastard
doh! Of course, you're right Drew - the contructor handles it.

Probably worth pointing out that this will only work if the instance is global. Otherwise the single instace can go out of scope and be deallocated, which is why I was trying to do it with 'new' I guess.
[size="1"]
Eric Poitras
Eric Poitras
ok now I'm confused, I though the whole idea of a singleton class was that I could have a class global and not worry about how it's constructed and destroyed, now if I just make a cCore class and make that global what would be the difference!? the only reason I'm doing this is to learn more efficient ways to code but so far I don't see any point to a singleton class.
All that is necessary for the triumph of evil is that good men do nothing. -Edmund Burke
Drew_Benton
Drew_Benton
Quote:
Original post by mrbastard
doh! Of course, you're right Drew - the contructor handles it.

Probably worth pointing out that this will only work if the instance is global. Otherwise the single instace can go out of scope and be deallocated, which is why I was trying to do it with 'new' I guess.


Oh no, you are definitly correct!. Personally, I don't like the way this template shows for singletons. I've never seen this one before. I'd definitlky go with new, but just for the sake of showing that this does indeed work, I just suggested to use the global, which yes does defeat the purpose [wink]

Quote:
Original post by Eric Poitras
ok now I'm confused, I though the whole idea of a singleton class was that I could have a class global and not worry about how it's constructed and destroyed, now if I just make a cCore class and make that global what would be the difference!? the only reason I'm doing this is to learn more efficient ways to code but so far I don't see any point to a singleton class.


I should just say, that yes what I said was dumb and is not how you use it, but as I previously said, that's one way to show this does work. I mean now that you know it works, I'd look for the way it is supposed to be, just seeing all those errors, didn't want you to give up with the design [wink]. Now as MrB has said about the new, that is definitly the way to do, so keep working with that one. Sorry for the confusion! [embarrass]

I kind of liked this method of doing it [smile], but there may be better ways of course. I don't care for the one in GPG 1
Hamster
Hamster
At the start of main, put this:


new cCore();



At the end of main, just before return, put this:


delete cCore::GetSingletonPtr();



The new will assign memory, and the delete makes sure you give it back to the operating system at the end. In between, you can use the class using your g_cCore macro and everything should work out fine.

Edit: fixed tags
x_gamer_x
x_gamer_x
What I do is:

static T& GetSingleton( void )   {      if(!ms_Singleton)        ms_Singleton = new T;     return (*ms_Singleton);   }


So the first time you use GetSingleton, it will create the instance. From then on, it will just return you the reference to that same instance. Just make sure you initialize ms_Singleton to 0.
Feral
Feral
Quote:
Original post by Eric Poitras
ok now I'm confused, I though the whole idea of a singleton class was that I could have a class global and not worry about how it's constructed and destroyed, now if I just make a cCore class and make that global what would be the difference!? the only reason I'm doing this is to learn more efficient ways to code but so far I don't see any point to a singleton class.


As I see it the point of a singleton of this style is thus:

1. You create it when you want (does not need to be global), thus you determine it's lifetime.
2. You have convent access (think global) to *JUST* the one instance of the class.

So, global access to something that is not global. While this may sound like a recipe for disaster it actually works pretty well.

[Edited by - Feral on April 12, 2005 3:11:36 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.