Singleton Object
-
- Greenskin
- Posts: 132
- Joined: Mon Aug 02, 2004 7:40 am
- Location: Austin, Texas
Singleton Object
I have been seeing a lot of references to Singletons and using them as such and such interface etc.. but I don't actually know what one is. I didn't see it in the Ogre manual in the Core Objects section (all I see that is similar sounding is the Root part).
Is it Ogre specific? 3d specific? C++ specific?
Thanks.
Is it Ogre specific? 3d specific? C++ specific?
Thanks.
-
- Gold Sponsor
- Posts: 446
- Joined: Fri May 02, 2003 10:05 am
- Location: UK
I found the tutorials over at GameTutorials very good when I was starting out with C++ and OpenGL etc so I recommend them to other beginners. Most of the tutorials are presented as VC projects with heavily commented source code.
At the bottom of the page on this link is one about singletons, check it out:
http://www.gametutorials.com/Tutorials/c++/Cpp_Pg6.htm
If you find it confusing, your probably best starting at the earlier tutorials first.
At the bottom of the page on this link is one about singletons, check it out:
http://www.gametutorials.com/Tutorials/c++/Cpp_Pg6.htm
If you find it confusing, your probably best starting at the earlier tutorials first.
-
- Goblin
- Posts: 272
- Joined: Wed Jun 02, 2004 11:47 am
- Location: Erlangen
I think a Singleton is just one way to get global access to classes you only need once (managers etc)
so you can for example access the class Ogre::Root from everywhere by doing
This way you don't have to pass throu a pointer of every single-instance-object to your own classes.
so you can for example access the class Ogre::Root from everywhere by doing
Code: Select all
Ogre::Root::getSingleton().someMemberOfRoot
-
- Halfling
- Posts: 55
- Joined: Mon Jun 07, 2004 11:01 am
Its a c++= thing
Singleton Classes rock. Simply think of it as a way of ensuring that the class you are calling is created only once. That means it can be called from anywhere ( by including header of course ) and you know that your calling the 1 static instance and not creating another instance.
I use them mostly for my main application and then for every single "manager" class that I use.
Here is an example of a Menu manager
And the .cpp
So in any other file i simply include
And I gain acess to it Knowing that its the one and only and not another instance.
Hope that clears it up a bit.
Singleton Classes rock. Simply think of it as a way of ensuring that the class you are calling is created only once. That means it can be called from anywhere ( by including header of course ) and you know that your calling the 1 static instance and not creating another instance.
I use them mostly for my main application and then for every single "manager" class that I use.
Here is an example of a Menu manager
Code: Select all
// Class Declaration
class MenuManager
{
public :
// Constructor
MenuManager();
// Destructor
~MenuManager();
// SingleTon Instance
// Singleton Instance of our Menu manager
static MenuManager &Instance();
// Create Main Menu
void CreateMainMenu();
private:
InheritedBase *m_BaseMenu;
MainMenu * m_MainMenu;
};
And the .cpp
Code: Select all
//SingleTon Instance
MenuManager &MenuManager::Instance()
{
static MenuManager instance;
return instance;
}
// Create MainMenu
void MenuManager::CreateMainMenu()
{
m_MainMenu = new MainMenu();
m_MainMenu->CreateMainMenu();
}
So in any other file i simply include
Code: Select all
#include MenuManager.h
Code: Select all
MenuManager::Instance().CreateMainMenu();
PrimedGames
www.PrimedGames.com
Email Me At
Mdobele( AT )primedgames.com
// Replace AT with @ of course
www.PrimedGames.com
Email Me At
Mdobele( AT )primedgames.com
// Replace AT with @ of course
-
- Greenskin
- Posts: 100
- Joined: Thu Dec 09, 2004 7:29 pm
- Location: Geluwe, Belgium
IIRC, singletons are a design pattern (a way of creating classes that fits in most projects). There are a lot of different implementations but the point is always the same: having ONLY ONE instance of a class.
http://www.gamedev.net/reference/articl ... le1825.asp => the basics
http://www.codeproject.com/gen/design/singleton.asp => some more difficult examples
http://www.gamedev.net/reference/articl ... le1825.asp => the basics
http://www.codeproject.com/gen/design/singleton.asp => some more difficult examples
-
- Gnoblar
- Posts: 9
- Joined: Wed Mar 03, 2004 5:34 pm
-
- OGRE Retired Team Member
- Posts: 19269
- Joined: Sun Oct 06, 2002 11:19 pm
- Location: Guernsey, Channel Islands
- x 66
-
- Greenskin
- Posts: 132
- Joined: Mon Aug 02, 2004 7:40 am
- Location: Austin, Texas
Thanks for the awesome answers everyone:
****************WIKIED*******************
****************WIKIED*******************
-
- Gnome
- Posts: 365
- Joined: Mon Jan 03, 2005 11:56 am
Let me show you the "Meyers Singleton", which IMO is the best general-purpose singleton implementation.
The "Singleton" class above would be called "MenuManager" or whatever you need. The rest of the class implementation is up to you. If you build on the bones of the above implementation your class will be a singleton.
Advantages of the Meyers singleton:
- simple to implement and understand
- it is not possible to create > 1 (because constructor is protected)
- the singleton is created on demand (this is both good and bad depending on circumstances)
- good: if singletons require each other during start-up you should be fine (unless you have cyclic dependencies)
- bad: if you want stuff to be preloaded (though this could be done elsewhere with a Singleton::getSingleton() call)
Disadvantages:
- must be reimplemented for each singleton class
- does not manage destruction dependencies, and if your singletons use each other during destruction you can get some subtle problems
Code: Select all
class Singleton
{
public:
static Singleton& getSingleton()
{
static Singleton instance;
return instance;
}
~Singleton();
protected:
Singleton();
};
Advantages of the Meyers singleton:
- simple to implement and understand
- it is not possible to create > 1 (because constructor is protected)
- the singleton is created on demand (this is both good and bad depending on circumstances)
- good: if singletons require each other during start-up you should be fine (unless you have cyclic dependencies)
- bad: if you want stuff to be preloaded (though this could be done elsewhere with a Singleton::getSingleton() call)
Disadvantages:
- must be reimplemented for each singleton class
- does not manage destruction dependencies, and if your singletons use each other during destruction you can get some subtle problems
-
- OGRE Retired Team Member
- Posts: 19269
- Joined: Sun Oct 06, 2002 11:19 pm
- Location: Guernsey, Channel Islands
- x 66
I hate to disagree with anything Meyers says, but I still prefer explicit instantiation of singletons personally. It's much more obvious to see what's going on, instead of trying to figure out which call to getSingleton() actually does the creation. Sure, you have to make sure you do it, but I prefer clearer code.
However, the major clincher is that Meyer's doesn't allow for specialised singletons. For example, TextureManager is a singleton, but it's never an instance of TextureManager - it's created by plugins and will be D3D9TextureManager, GLTextureManager etc. Meyer's approach doesn't allow that.
However, the major clincher is that Meyer's doesn't allow for specialised singletons. For example, TextureManager is a singleton, but it's never an instance of TextureManager - it's created by plugins and will be D3D9TextureManager, GLTextureManager etc. Meyer's approach doesn't allow that.
-
- Gnome
- Posts: 365
- Joined: Mon Jan 03, 2005 11:56 am
I don't think you're really disagreeing with Meyers, this is simply a technique he popularised. I'm sure he would agree with the trade-offs you point out.sinbad wrote:I hate to disagree with anything Meyers says, but I still prefer explicit instantiation of singletons personally. It's much more obvious to see what's going on, instead of trying to figure out which call to getSingleton() actually does the creation. Sure, you have to make sure you do it, but I prefer clearer code.
Although the no-specialised-singletons is a pure disadvantage, not a trade-off.
-
- OGRE Community Helper
- Posts: 198
- Joined: Sat Oct 02, 2004 9:11 am
- Location: San Francisco, California, USA
I have to say, the singleton design pattern is overrated. I have never seen a good use of it that wasn't identical to using the keyword "static". It's a design choice; not a /bad/ one, but it really doesn't serve much of a purpose in my eyes. It just makes for visual code bloat.
Q: What's the major difference between deriving Ogre::Root from Singleton<Ogre::Root>, and keeping a global Root* pointer in the Ogre namespace?
A: One requires you to call Ogre::Root::getSingleton() everywhere, and the other doesn't. They compile to equivalent code.
OK, so singletons prevent you from accidentally creating multiple instances of the class. But under what circumstances would that ever be an issue?
What it comes down to, I guess, is that singletons are good for cases where you don't trust your user and you want to keep him/her from screwing things up. But there are other ways of doing this (protected constructor with static Create function, etc) that don't involve spewing "Class::getSingleton()" all over the place.
Q: What's the major difference between deriving Ogre::Root from Singleton<Ogre::Root>, and keeping a global Root* pointer in the Ogre namespace?
A: One requires you to call Ogre::Root::getSingleton() everywhere, and the other doesn't. They compile to equivalent code.
OK, so singletons prevent you from accidentally creating multiple instances of the class. But under what circumstances would that ever be an issue?
What it comes down to, I guess, is that singletons are good for cases where you don't trust your user and you want to keep him/her from screwing things up. But there are other ways of doing this (protected constructor with static Create function, etc) that don't involve spewing "Class::getSingleton()" all over the place.
-
- Gnome
- Posts: 365
- Joined: Mon Jan 03, 2005 11:56 am
In C++, when you have non-local static objects in different translation units you have no control over their order of creation. Therefore, if you have two global static objects in different translation units and one uses the other during construction, you are possibly in for some of that lovely undefined behaviour. Making your static objects local (as within a getSingleton method) solves the problem neatly.qsilver wrote:Q: What's the major difference between deriving Ogre::Root from Singleton<Ogre::Root>, and keeping a global Root* pointer in the Ogre namespace?
A: One requires you to call Ogre::Root::getSingleton() everywhere, and the other doesn't. They compile to equivalent code.
-
- OGRE Retired Moderator
- Posts: 4011
- Joined: Fri Sep 19, 2003 6:28 pm
- Location: Burgos, Spain
- x 2
Using global variables has the called "side effects". I personally find them extremely util, but too dangerous to use.
About static properties, I recently read about a singleton-hack (at least for me) pattern called Monostate. It consists in simply make all the properties (both attributes and methods) static. I'm still wandering the pros and cons of this. Seems more versatile and simple, but the fact that the singleton is so used instead of the monostate akes me guess why...
About static properties, I recently read about a singleton-hack (at least for me) pattern called Monostate. It consists in simply make all the properties (both attributes and methods) static. I'm still wandering the pros and cons of this. Seems more versatile and simple, but the fact that the singleton is so used instead of the monostate akes me guess why...
-
- OGRE Community Helper
- Posts: 198
- Joined: Sat Oct 02, 2004 9:11 am
- Location: San Francisco, California, USA
The static singleton pointer is class local, not function local, meaning that it is still initialized at an undefined time. You might as well use a global pointer and save the repeated typing of getSingleton().alphageek wrote:In C++, when you have non-local static objects in different translation units you have no control over their order of creation. Therefore, if you have two global static objects in different translation units and one uses the other during construction, you are possibly in for some of that lovely undefined behaviour. Making your static objects local (as within a getSingleton method) solves the problem neatly.
-
- OGRE Retired Moderator
- Posts: 4823
- Joined: Fri Jun 18, 2004 1:40 pm
- Location: Berlin, Germany
- x 7
qsilver, the point of a singleton is, as the name suggests, that it allows only one instance of a class. In Meyer's implementation this is ensured with a private/protected constructor, in Ogre's with an assert statement.
Your implementation doesn't prevent multiple Root instances. It, of course, can be extended with a few quirks, but I doubt the result would be more elegant than a real Singleton.
Your implementation doesn't prevent multiple Root instances. It, of course, can be extended with a few quirks, but I doubt the result would be more elegant than a real Singleton.
-
- OGRE Community Helper
- Posts: 198
- Joined: Sat Oct 02, 2004 9:11 am
- Location: San Francisco, California, USA
I have to ask, if there's only supposed to be one of it, then why is it an object in the first place
But even so, it seems to me that a Singleton is only useful if you do not trust the programmer. It is nothing more than a way of telling the user, "you should not have done that." The pattern only exists to limit the programmer, which to me is a horrible justification. But if you really wanted to enforce one-time construction, it could be as simple as putting (static bool init = false; assert(!init); init = true;) in the constructor.
The first line of my main function is:... and I've probably saved several KB of source code at this point from not calling Root::getSingleton() all over the place.
But I guess I'm just doomed to disagree with Meyer and all the various practices that have come out of formalized software engineering
But even so, it seems to me that a Singleton is only useful if you do not trust the programmer. It is nothing more than a way of telling the user, "you should not have done that." The pattern only exists to limit the programmer, which to me is a horrible justification. But if you really wanted to enforce one-time construction, it could be as simple as putting (static bool init = false; assert(!init); init = true;) in the constructor.
The first line of my main function is:
Code: Select all
gRoot = new Ogre::Root();
But I guess I'm just doomed to disagree with Meyer and all the various practices that have come out of formalized software engineering
-
- OGRE Retired Team Member
- Posts: 390
- Joined: Sun Oct 06, 2002 11:19 pm
- Location: The Woodlands, TX
This is devolving into an argument about who is in charge of choices, the library dev or the library user. Let's not go there, it never gets solved. In general C++ tends to want the library developer to make the usage patterns explicit. A counter example would be python where it's up to the user to know what their asking for and pushing into the library/module.
If there aren't any more comments specific to singletons, let's get off it.
If there aren't any more comments specific to singletons, let's get off it.
-
- Gnome
- Posts: 365
- Joined: Mon Jan 03, 2005 11:56 am
No no. In the Meyers singleton, the singleton instance *is* function local to the getSingleton method.qsilver wrote:The static singleton pointer is class local, not function local, meaning that it is still initialized at an undefined time. You might as well use a global pointer and save the repeated typing of getSingleton().alphageek wrote:In C++, when you have non-local static objects in different translation units you have no control over their order of creation. Therefore, if you have two global static objects in different translation units and one uses the other during construction, you are possibly in for some of that lovely undefined behaviour. Making your static objects local (as within a getSingleton method) solves the problem neatly.
Code: Select all
// .cpp
Singleton& Singleton::getSingleton()
{
static Singleton instance;
return instance;
}
-
- OGRE Community Helper
- Posts: 198
- Joined: Sat Oct 02, 2004 9:11 am
- Location: San Francisco, California, USA
Ah, my mistake. I haven't seen his book in quite a while ...
Anyway, I agree then with Meyer's implementation of Singletons; it seems like a reasonable way to do things, if not the method that I would choose. I'm not so hot on Ogre's implementation using a global-level pointer, but I've said that before, so I'll stop harping on it
But if anyone else is still reading this thread, I suppose the important thing to take away from all this is that singletons are not absolutely necessary, but they are useful to demonstrate that an object is meant to be created only once.
Anyway, I agree then with Meyer's implementation of Singletons; it seems like a reasonable way to do things, if not the method that I would choose. I'm not so hot on Ogre's implementation using a global-level pointer, but I've said that before, so I'll stop harping on it
But if anyone else is still reading this thread, I suppose the important thing to take away from all this is that singletons are not absolutely necessary, but they are useful to demonstrate that an object is meant to be created only once.
-
- Goblin
- Posts: 282
- Joined: Tue Jan 04, 2005 6:56 pm
- Location: The Netherlands
Out of interest, what is the difference with a class local singleton instance? Apart from being able to use the same singleton instance in a DestroyInstance() function, I don't see any difference or reason to prefer one or the other? (though I think that would only be needed if it was a pointer rather then a reference)alphageek wrote:No no. In the Meyers singleton, the singleton instance *is* function local to the getSingleton method.qsilver wrote:The static singleton pointer is class local, not function local, meaning that it is still initialized at an undefined time. You might as well use a global pointer and save the repeated typing of getSingleton().alphageek wrote:In C++, when you have non-local static objects in different translation units you have no control over their order of creation. Therefore, if you have two global static objects in different translation units and one uses the other during construction, you are possibly in for some of that lovely undefined behaviour. Making your static objects local (as within a getSingleton method) solves the problem neatly.
Code: Select all
// .cpp Singleton& Singleton::getSingleton() { static Singleton instance; return instance; }
Proud member of the OpenFRAG Game Development community
-
- Gnome
- Posts: 365
- Joined: Mon Jan 03, 2005 11:56 am
Well I think you have the same problem with class-local static data: you don't know anything about construction order across translation units.BRAINLESS wrote: Out of interest, what is the difference with a class local singleton instance? Apart from being able to use the same singleton instance in a DestroyInstance() function, I don't see any difference or reason to prefer one or the other? (though I think that would only be needed if it was a pointer rather then a reference)
It's only function-local static data that you know is initialised the first time that function is executed.
Yeah. I use them quite often, but I should probably only use them when construction order matters for multiple globally accessible objects.qsilver wrote:I suppose the important thing to take away from all this is that singletons are not absolutely necessary
-
- OGRE Retired Team Member
- Posts: 19269
- Joined: Sun Oct 06, 2002 11:19 pm
- Location: Guernsey, Channel Islands
- x 66
No design pattern is 'absolutely necessary'. You don't need iterators or function objects but that doesn't mean you shouldn't use them. The point is that it's a recognisable and proven solution to a common problem. They help people get up to speed with unfamiliar code quicker, and save design time. Everyone doing their own personal solutions makes code harder to read and understand and leads to more bugs. Sure it's fairly trivial in the Singleton case, but that's not the point. The principle counts.qsilver wrote:But if anyone else is still reading this thread, I suppose the important thing to take away from all this is that singletons are not absolutely necessary, but they are useful to demonstrate that an object is meant to be created only once.
And IMO, global pointers are ugly. Sure, the singleton equates to the same underlying thing when you use explicit construction, but in the same way as putting all your code on one line in C++ equates to the same thing. You can do it, it takes up less space, but that doesn't mean it's better.
-
- Gnoblar
- Posts: 17
- Joined: Sun Feb 27, 2005 12:13 am
- Location: Australia