DevMaster.net Forums
[[ Home | Forums | 3D Engines Database | Wiki | Articles/Tutorials | Game Dev Jobs | IRC Chat Network | Contact Us ]]

Go Back   DevMaster.net Forums > Site Discussions > Code & Snapshot Discussion
User Name
Password
Register FAQ Members List Search Today's Posts Mark Forums Read

Reply
 
Thread Tools Search this Thread Display Modes
Old 08-25-2004, 09:09 PM   #1
john
Member
 
Join Date: Jan 2003
Posts: 85
Default

For those who don't know, a Singleton is an object that can only have one instance in the lifetime of the program. Here's the class to inherit from to make a singleton class. This is taken from the GEMS series.

Singleton.h
-------------
Code:
#ifdef _MSVC // Turn off warnings generated by this singleton implementation #pragma warning (disable : 4311) #pragma warning (disable : 4312) #endif template <typename T> class Singleton { protected: static T* ms_Singleton; public: Singleton() { assert( !ms_Singleton ); int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1; ms_Singleton = (T*)((int)this + offset); } ~Singleton() { assert( ms_Singleton ); ms_Singleton = 0; } static T* getSingleton() { return ms_Singleton; } }; } #endif

Example of usage:
-----------------------
Code:
// common sense says you can only have one instance of an opengl renderer class OpenGLRenderer : public Singleton<OpenGLRenderer> { ... void SomeMethod() { printf("Hello world!"); } };

Now OpenGLRenderer can only be created once. Attempting to create again (using the 'new' keyword) will cause an assertion to warn you. Example of usage:

Code:
int main() { new OpenGLRenderer; OpenGLRenderer::getSingleton()->SomeMethod(); .... delete OpenGLRenderer::getSingleton(); // delete before exiting program return 0; }
john is offline   Reply With Quote
Old 08-26-2004, 12:52 AM   #2
bladder
DevMaster Staff
 
bladder's Avatar
 
Join Date: Sep 2003
Location: Hell
Posts: 1,109
Default

you shouldn't use that hacky offset thing in teh ctor becaus eof incompatability issues. a simple static_cast would do just fine, and here's why

and for those that are inerested, here's the online description of that from the guy who wrot eit in the gems book.
___________________________________________
- TripleBuffer
- Me blog
bladder is offline   Reply With Quote
Old 08-26-2004, 06:09 AM   #3
anubis
DevMaster Staff
 
anubis's Avatar
 
Join Date: Apr 2003
Location: Germany
Posts: 2,328
Default

especially since i see no real need for this class at all. the thing is that as soon as you start using dlls your singleton pointer won't work over library boundaries because each dll would reimplement the static pointer locally. to solve this you would have to provide a static overload of the getSingleton method in each class that derives from Singleton. what remains is that you have abstracted the storage of the singleton pointer in a hacky and ugly way (the static_cast would take away the uglyness but still the whole thing would be more of an OOP beautification than being really useful)
___________________________________________
If Prolog is the answer, what is the question ?
anubis is offline   Reply With Quote
Old 08-26-2004, 06:22 AM   #4
davepermen
Senior Member
 
davepermen's Avatar
 
Join Date: Jan 2003
Location: Switzerland
Posts: 1,333
Default

i hate singletons.. but okay.. having it around is fine (for more details about why, just browse the net.. there are tons of discussions)
___________________________________________
davepermen.net
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
davepermen is offline   Reply With Quote
Old 08-26-2004, 06:42 AM   #5
NomadRock
Senior Member
 
NomadRock's Avatar
 
Join Date: Aug 2004
Location: USA
Posts: 829
Default

It is not something I would ever use but it is still neat to see a singleton implemented as an inhereted templated class that takes its decendant as a parameter. I wonder if code errors are produced in programs by inbreading just as they are in people.

I do question what happens when you make a subclass of your chosen singleton. I suppose you would have to resign yourself to never doing this. Though I guess you could always recast the returned pointer by hand afterward.
___________________________________________
Jesse Coyle
NomadRock is offline   Reply With Quote
Old 09-08-2004, 12:16 PM   #6
knackered
New Member
 
Join Date: Sep 2004
Posts: 9
Default

Only want one opengl renderer?! Maybe in a very simple application, like a game. Not in, say, tools.

Anyway, what's wrong with:-
Code:
.h class OpenGLRenderer { public: static OpenGLRenderer& Singleton(); }; .cpp OpenGLRenderer& OpenGLRenderer::Singleton() { static OpenGLRenderer s; return s; }

The object isn't constructed until Singleton is first called, and it works across DLL's.
knackered is offline   Reply With Quote
Old 09-08-2004, 02:19 PM   #7
davepermen
Senior Member
 
davepermen's Avatar
 
Join Date: Jan 2003
Location: Switzerland
Posts: 1,333
Default

nothings wrong with it. we still have to care manually about uninitialisation of the renderer. and still, singletons are not my thing, i don't like them.
___________________________________________
davepermen.net
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
davepermen is offline   Reply With Quote
Old 09-09-2004, 01:13 AM   #8
Mihail121
Senior Member
 
Mihail121's Avatar
 
Join Date: Jan 2003
Posts: 868
Default

I doupt that someone likes them cause in the most cases their implementation is extremely hacky like the one above.

And i remember seeing in the HL2 sources (which of course i don't have on my hard disk!!!) that Valve also uses the most simple variant knackered showed.

However this implementation posses great danger about deinitialization since i'm not exactly sure when the destructor is called...
Mihail121 is offline   Reply With Quote
Old 09-09-2004, 01:30 AM   #9
knackered
New Member
 
Join Date: Sep 2004
Posts: 9
Default

Destruction happens when the module is unloaded, or the application terminates in the same way that all other statics are destructed. The order of statics destruction is undefined, however.
knackered is offline   Reply With Quote
Old 09-09-2004, 08:01 AM   #10
davepermen
Senior Member
 
davepermen's Avatar
 
Join Date: Jan 2003
Location: Switzerland
Posts: 1,333
Default

yeah, and this order can be important sometimes.

but my main reason i don't like singletons is another one. where-ever i design some sort of object, even while i think i will only need it once, and only once, there will be the day i just put it into vector, or what ever, and have several of them.

i never had a singleton that survived for long time as a real singleton, and ended as just another class, with possibly a global interface to the instances. but about never it stayed at only one instance..

well well.. my little rant about singletons..
___________________________________________
davepermen.net
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
davepermen is offline   Reply With Quote
Old 09-09-2004, 09:04 AM   #11
NomadRock
Senior Member
 
NomadRock's Avatar
 
Join Date: Aug 2004
Location: USA
Posts: 829
Default

Dave, that is actually the entire reason for using Singletons instead of a bunch of global functions or a class of static functions. In this way the only change you have to make is to remove the getInstance function and make the constructor pubic and you are done.
___________________________________________
Jesse Coyle
NomadRock is offline   Reply With Quote
Old 09-09-2004, 09:33 AM   #12
Def Base
Member
 
Join Date: Sep 2004
Posts: 33
Default

Um, shouldn't the con/destructor in that code be made private, and a static GetInstance() method (or whatever) added to the class? Otherwise there's very little stopping you from buggering the whole implementation...
___________________________________________
Def Base
[ 32Bits.co.uk - Coding for real people! ]
Def Base is offline   Reply With Quote
Old 09-19-2004, 10:11 PM   #13
SnprBoB86
Valued Member
 
Join Date: Aug 2004
Posts: 120
Default

I am a huge advocate of OOP, but sometimes you just need to pick the best tool for the job. What I am saying is that you can build a singleton as free functions (with Init and Uninit functions) or, preferably, make your singleton a global pointer variable. That gives you full control over lifetime and eliminates any hack or weird singleton mechinism.

If you go with the global variable, you can add this line to your objects contructor:

ASSERT(pGlobal == NULL)

Simple and effective.
___________________________________________
Brandon Bloom
http://brandonbloom.name
SnprBoB86 is offline   Reply With Quote
Old 09-19-2004, 11:04 PM   #14
davepermen
Senior Member
 
davepermen's Avatar
 
Join Date: Jan 2003
Location: Switzerland
Posts: 1,333
Default

i don't see the purpose of "having a class that can only be instanciated once".

i do see the use of modules (often my factories are modules), and the fact that sometimes, i only want one global instance of my class. but restricting a class to only be instanciable one time. i see no use for this.. this sounds irritating.
___________________________________________
davepermen.net
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
davepermen is offline   Reply With Quote
Old 09-20-2004, 12:22 AM   #15
SpreeTree
Valued Member
 
SpreeTree's Avatar
 
Join Date: Jan 2004
Location: England
Posts: 265
Default

The singleton class here is very similar to the one posted in the Enginuity articles posted on GameDev. Useful to some but I had a lot of issues with it that ment that it had to be removed.

The offsetting code, while working in VS .net doesnt work in VC6, and, as has been mentioned, it is not a viable option when using dll's.

I would be interested to know how wide spread the use of proper sngletons is in general game programming, because for me, it is to restrictive, and in some cases, excessive for general use.

Spree
SpreeTree is offline   Reply With Quote
Old 11-14-2005, 08:27 PM   #16
Vexorian
New Member
 
Join Date: Oct 2005
Posts: 6
Default Re: Implementing a Singleton

Well if you are unable to implement singleton or are have too much problems doing it, you can try a class with all its members as static, and just add Setup() and End() methods or something.

With the help of a bool vairable you can make an Init function that initializes the 'class' as long as it wasn't initialized , for those cases where you can't be sure which modulo loads first

Last edited by Vexorian : 11-14-2005 at 08:51 PM.
Vexorian is offline   Reply With Quote
Old 11-15-2005, 01:20 AM   #17
Reedbeta
DevMaster Staff
 
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
Default Re: Implementing a Singleton

I agree with davepermen on this one. A singleton's just a hidden global variable, so why not just make it a global variable (in a namespace if you want)? Chances are, sooner or later you will think up a situation where you want to be able to have more than one instance of this class. The effort needed to implement a proper singleton in C++ is, imho, not worth its very dubious benefits.
___________________________________________
Currently working at Sucker Punch
reedbeta.com - OpenGL demos and other projects
Luabridge - a lightweight, dependency-free C++/Lua binding library.
CD Lite - an unobtrusive, minimal CD player application for Windows.
Reedbeta is offline   Reply With Quote
Old 11-15-2005, 06:17 AM   #18
.oisyn
DevMaster Staff
 
.oisyn's Avatar
 
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
Default Re: Implementing a Singleton

Reedbeta: global variables are poor design in the sense they can be altered. If you hide the variable with an accessor, you can only read the instance and not write.

Also, having to pass around tons of pointers can be pretty tedious, so having singleton accessors makes live much easier. If you really want to be able to create more than a single instance of a class, I suggest putting all the accessors in a class that also holds all the references to the singletons, so you can hold a single pointer to that class.
___________________________________________
C++ addict
-
Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3.
.oisyn is offline   Reply With Quote
Old 11-15-2005, 10:28 AM   #19
Reedbeta
DevMaster Staff
 
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
Default Re: Implementing a Singleton

Quote:
Originally Posted by .oisyn
...I suggest putting all the accessors in a class that also holds all the references to the singletons, so you can hold a single pointer to that class.

Yes, this is exactly what I do. I have a State class that holds all the things that would otherwise be global variables. There is typically just one global instance of this class, but it it allows for expansion to more (for instance, if I was writing a raytracer, I might want to expand it to a "render server" that could simultaneously process multiple independent rendering jobs).
___________________________________________
Currently working at Sucker Punch
reedbeta.com - OpenGL demos and other projects
Luabridge - a lightweight, dependency-free C++/Lua binding library.
CD Lite - an unobtrusive, minimal CD player application for Windows.
Reedbeta is offline   Reply With Quote
Old 11-16-2005, 12:36 AM   #20
anubis
DevMaster Staff
 
anubis's Avatar
 
Join Date: Apr 2003
Location: Germany
Posts: 2,328
Default Re: Implementing a Singleton

The Singleton is probably most useful, when you need to make clear to others, by design, that a class is supposed to exist only once in a system. Always remember that the people who write software architecutures and those who implement them are often not the same.

I agree though that especially on windows the pattern is plagued by far too many problems.
___________________________________________
If Prolog is the answer, what is the question ?
anubis is offline   Reply With Quote
Old 11-16-2005, 12:49 AM   #21
eddie
Senior Member
 
Join Date: Oct 2005
Posts: 745
Default Re: Implementing a Singleton

I do find that I side with Reedbeta in one aspect:

Most of my singletons end up marching up the line and end up becoming 'managed' instances: that is, I end up having more than one.

It's funny however then, because then the item that's 'managing' those instances usually becomes the singleton, and the singleton itself is relatively easy to extract from such an implementation.

On a somewhat related note: has anyone ever looked at Loki Lib? (http://sourceforge.net/projects/loki-lib/) It's supposed to make implementing design patterns such as the singleton much easier to roll out. I'm curious how it fares.
___________________________________________
Kicking Dragon (dot) com - Technical Ramblings of a Game Programmer
eddie is offline   Reply With Quote
Old 11-17-2005, 07:51 AM   #22
monjardin
Senior Member
 
Join Date: Oct 2005
Location: Pensacola, FL
Posts: 1,028
Default Re: Implementing a Singleton

I've had experiences with MSVC++ 7.1 optimizing out singleton implementations like the one knackered showed with the "Maximize Speed (/O2)" setting:

Code:
class Singleton { Singleton& singleton() { static Singleton instance; return instance; } };

It seems to make the code behave like this:

Code:
class Singleton { Singleton& singleton() { Singleton* instance = NULL; return *instance; } };

...and that's obviously bad.

Does anyone know how to predict and/or prevent this behavior? Or am I just crazy, and noone else has had this problem?
___________________________________________
monjardin's JwN Meter (1,2,3,4,5,6):
|----|----|----|----|----|----|----|----|----|----|
*
monjardin is offline   Reply With Quote
Old 11-17-2005, 08:32 AM   #23
.oisyn
DevMaster Staff
 
.oisyn's Avatar
 
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
Default Re: Implementing a Singleton

Are you sure? It works fine on my machine...

S.h
Code:
struct S { S(); ~S(); }; S & getInstance();

main.cpp:
Code:
#include <iostream> #include "S.h" S::S() { std::cout << "hello" << std::endl; } S::~S() { std::cout << "goodbye" << std::endl; } int main() { std::cout << &getInstance() << std::endl; }

foo.cpp:
Code:
#include "S.h" S & getInstance() { static S s; return s; }


output:
Code:
hello 00417320 goodbye
___________________________________________
C++ addict
-
Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3.

Last edited by .oisyn : 11-17-2005 at 08:34 AM.
.oisyn is offline   Reply With Quote
Old 11-17-2005, 08:56 AM   #24
monjardin
Senior Member
 
Join Date: Oct 2005
Location: Pensacola, FL
Posts: 1,028
Default Re: Implementing a Singleton

It definitely works most of the time. I've only had the problem once and I don't know why. Anyway, I've decided to avoid the use of singletons whenever possible. The case that caused the problem was a rush job in which the singletons substituted for good design.

NOTE: I'm not intending to start another singletons are bad discussion! I don't have enough experience to comment either way.
___________________________________________
monjardin's JwN Meter (1,2,3,4,5,6):
|----|----|----|----|----|----|----|----|----|----|
*
monjardin is offline   Reply With Quote
Old 11-18-2005, 05:04 PM   #25
m4x0r
New Member
 
Join Date: Aug 2005
Location: San Francisco, MA
Posts: 24
Default Re: Implementing a Singleton

Quote:
Originally Posted by anubis
especially since i see no real need for this class at all. the thing is that as soon as you start using dlls your singleton pointer won't work over library boundaries because each dll would reimplement the static pointer locally. to solve this you would have to provide a static overload of the getSingleton method in each class that derives from Singleton.

Can you elaborate on this? I've never had any problem with exporting from a DLL a class derived from a singleton template like this one. I have had problems when the derived class was also templated, but that can be solved by exporting specializations of the singleton.

Max
m4x0r is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Forum Jump


All times are GMT -7. The time now is 08:39 AM.


Powered by vBulletin
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.