Singleton Object

Get answers to all your basic programming questions. No Ogre questions, please!
User avatar
bana
Greenskin
Posts: 132
Joined: Mon Aug 02, 2004 7:40 am
Location: Austin, Texas
Contact:

Singleton Object

Post by bana »

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.
A proud member of the OpenFrag Coding Team.
http://coolhands.blogspot.com/
User avatar
SpannerMan
Gold Sponsor
Gold Sponsor
Posts: 446
Joined: Fri May 02, 2003 10:05 am
Location: UK
Contact:

Post by SpannerMan »

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.
User avatar
Emmeran
Goblin
Posts: 272
Joined: Wed Jun 02, 2004 11:47 am
Location: Erlangen
Contact:

Post by Emmeran »

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

Code: Select all

Ogre::Root::getSingleton().someMemberOfRoot
This way you don't have to pass throu a pointer of every single-instance-object to your own classes.
Mdobele
Halfling
Posts: 55
Joined: Mon Jun 07, 2004 11:01 am
Contact:

Post by Mdobele »

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

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
And I gain acess to it Knowing that its the one and only and not another instance.

Code: Select all

MenuManager::Instance().CreateMainMenu();
Hope that clears it up a bit.
PrimedGames
www.PrimedGames.com

Email Me At
Mdobele( AT )primedgames.com
// Replace AT with @ of course
User avatar
bal
Greenskin
Posts: 100
Joined: Thu Dec 09, 2004 7:29 pm
Location: Geluwe, Belgium

Post by bal »

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
fraggle
Gnoblar
Posts: 9
Joined: Wed Mar 03, 2004 5:34 pm

Post by fraggle »

I haven't tried it, but is a singleton limited to one thread or one process?
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19265
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Post by sinbad »

No, Singletons are not thread local so you can access them from any thread. Note though that they're also not thread safe unless they say so (e.g. ResourceGroupManagager and ResourceManager in Azathoth), so be careful if you do access them from multiple threads.
User avatar
haffax
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4823
Joined: Fri Jun 18, 2004 1:40 pm
Location: Berlin, Germany
x 6
Contact:

Post by haffax »

This depends on your implementation, it is not singleton specific. If all member methods are thread save, you won't have any problems.
team-pantheon programmer
creators of Rastullahs Lockenpracht
User avatar
bana
Greenskin
Posts: 132
Joined: Mon Aug 02, 2004 7:40 am
Location: Austin, Texas
Contact:

Post by bana »

Thanks for the awesome answers everyone:

****************WIKIED*******************
A proud member of the OpenFrag Coding Team.
http://coolhands.blogspot.com/
User avatar
alphageek
Gnome
Posts: 365
Joined: Mon Jan 03, 2005 11:56 am

Post by alphageek »

Let me show you the "Meyers Singleton", which IMO is the best general-purpose singleton implementation.

Code: Select all

class Singleton
{
  public:
  static Singleton& getSingleton()
  {
    static Singleton instance;
    return instance;
  }

  ~Singleton();

  protected:
  Singleton();

};
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
Axiomatic: action-packed space shooter
TaskScheduler 0.3
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19265
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Post by sinbad »

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.
User avatar
alphageek
Gnome
Posts: 365
Joined: Mon Jan 03, 2005 11:56 am

Post by alphageek »

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.
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.
Although the no-specialised-singletons is a pure disadvantage, not a trade-off.
Axiomatic: action-packed space shooter
TaskScheduler 0.3
qsilver
OGRE Community Helper
OGRE Community Helper
Posts: 198
Joined: Sat Oct 02, 2004 9:11 am
Location: San Francisco, California, USA

Post by qsilver »

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.
User avatar
alphageek
Gnome
Posts: 365
Joined: Mon Jan 03, 2005 11:56 am

Post by alphageek »

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.
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.
Axiomatic: action-packed space shooter
TaskScheduler 0.3
User avatar
Kencho
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4011
Joined: Fri Sep 19, 2003 6:28 pm
Location: Burgos, Spain
x 2
Contact:

Post by Kencho »

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... :roll:
Image
qsilver
OGRE Community Helper
OGRE Community Helper
Posts: 198
Joined: Sat Oct 02, 2004 9:11 am
Location: San Francisco, California, USA

Post by qsilver »

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.
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().
User avatar
haffax
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4823
Joined: Fri Jun 18, 2004 1:40 pm
Location: Berlin, Germany
x 6
Contact:

Post by haffax »

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. ;)
team-pantheon programmer
creators of Rastullahs Lockenpracht
qsilver
OGRE Community Helper
OGRE Community Helper
Posts: 198
Joined: Sat Oct 02, 2004 9:11 am
Location: San Francisco, California, USA

Post by qsilver »

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:

Code: Select all

gRoot = new Ogre::Root();
... 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 :)
User avatar
temas
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 390
Joined: Sun Oct 06, 2002 11:19 pm
Location: The Woodlands, TX
Contact:

Post by temas »

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.
User avatar
alphageek
Gnome
Posts: 365
Joined: Mon Jan 03, 2005 11:56 am

Post by alphageek »

qsilver wrote:
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.
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().
No no. In the Meyers singleton, the singleton instance *is* function local to the getSingleton method.

Code: Select all

// .cpp
Singleton& Singleton::getSingleton()
{
  static Singleton instance;
  return instance;
}
Axiomatic: action-packed space shooter
TaskScheduler 0.3
qsilver
OGRE Community Helper
OGRE Community Helper
Posts: 198
Joined: Sat Oct 02, 2004 9:11 am
Location: San Francisco, California, USA

Post by qsilver »

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.
User avatar
BRAINLESS
Goblin
Posts: 282
Joined: Tue Jan 04, 2005 6:56 pm
Location: The Netherlands

Post by BRAINLESS »

alphageek wrote:
qsilver wrote:
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.
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().
No no. In the Meyers singleton, the singleton instance *is* function local to the getSingleton method.

Code: Select all

// .cpp
Singleton& Singleton::getSingleton()
{
  static Singleton instance;
  return instance;
}
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)
Proud member of the OpenFRAG Game Development community
User avatar
alphageek
Gnome
Posts: 365
Joined: Mon Jan 03, 2005 11:56 am

Post by alphageek »

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)
Well I think you have the same problem with class-local static data: you don't know anything about construction order across translation units.

It's only function-local static data that you know is initialised the first time that function is executed.
qsilver wrote:I suppose the important thing to take away from all this is that singletons are not absolutely necessary
Yeah. I use them quite often, but I should probably only use them when construction order matters for multiple globally accessible objects. ;)
Axiomatic: action-packed space shooter
TaskScheduler 0.3
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19265
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Post by sinbad »

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.
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.

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. ;)
mr_smith
Gnoblar
Posts: 17
Joined: Sun Feb 27, 2005 12:13 am
Location: Australia

Post by mr_smith »

Don't you need to declare the copy constructor be to private in order to be sure you only have one instance?
Post Reply