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 12-08-2007, 08:00 AM   #1
Eric B
 
Posts: n/a
Default

This is standard singleton implementation, with a twist from my own.

First, I write the singleton implementation code:
Code:
class MySingletonImpl { public: void DoSomething(); };

Followed by what I call a handle:
Code:
class MySingleton { public: MySingleton() { if (MySingleton::instance == NULL) { instance = new MySingletonImpl(); } } void DoSomething() { MySingleton::instance->DoSomething(); } private: static MySingletonImpl* instance; }; MySingletonImpl* MySingleton::MySingletonImpl = NULL;
Inside the handle class, we can do whatever we want with the real singleton instance. We could even do some lifetime policy management.

Then, to use this singleton, you instanciate a handle like so:
Code:
int main() { MySingleton s; s.DoSomething(); DoItAgain(); } void DoItAgain() { MySingleton s; s.DoSomething(); }

What do you think?
Eric B.
  Reply With Quote
Old 12-08-2007, 11:35 AM   #2
Reedbeta
DevMaster Staff
 
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
Default Re: Singleton handles

I think that's a cool way of doing it. It certainly makes using the singleton syntactically nicer (no MySingleton::getInstance junk everywhere). And because you have another layer between the users and the actual singleton object, you have a bit more flexibility about policy; you could easily change from a true global singleton to a one-per-thread 'singleton', for instance.

On the other hand, you have to write a forwarding method for every method of the singleton (and update these every time the singleton's methods change). Also there's nothing in the code you showed about controlling destruction order, which can be an issue (though your method does allow construction order to be controlled rather elegantly).
___________________________________________
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.

Last edited by Reedbeta : 12-09-2007 at 01:39 PM.
Reedbeta is offline   Reply With Quote
Old 12-08-2007, 02:21 PM   #3
J22
Member
 
Join Date: Jul 2007
Posts: 92
Default Re: Singleton handles

Or you could create a singleton smart pointer:
Code:
template<class T> class SingletonPtr { public: SingletonPtr() { if(!s_ptr) s_ptr=new T(); } T *operator->() { return s_ptr; } private: static T *s_ptr; }; template<class T> T *SingletonPtr<T>::s_ptr=0; class A { public: void foo() {} private: friend class SingletonPtr<A>; A() {} A(const A&); };
And use it like:
Code:
SingletonPtr<A> ptr; ptr->foo();
Not sure if this is any better than Singleton<A>::GetPtr(); though

Last edited by J22 : 12-08-2007 at 02:25 PM.
J22 is offline   Reply With Quote
Old 12-09-2007, 06:45 AM   #4
Nautilus
Valued Member
 
Join Date: Nov 2004
Location: Milan -ITALY-
Posts: 297
Default Re: Singleton handles

Hi,
one wouldn't want the singleton to auto-delete as one of the instances of the handler class goes out of scope, so invoking a delete from inside a destructor is not an option.
Therefore the handler class could expose a method to be explicitly invoked (by the client) when he wishes to release the singleton.
Since the singleton is handled through a static pointer, nulling it will safely affect each and every instance of the handler class still in scope, and for free too.

Ciao ciao : )
___________________________________________
-Nautilus

1.551640271931635485e+1292913986 ?
Why, that's: 2 ^ ((2 ^ (2 ^ ((2 ^ 2) + (2 ^ (2 - 2))))) - (2 ^ (2 - 2))). Now verify, please...
Nautilus is offline   Reply With Quote
Old 12-09-2007, 11:25 AM   #5
Jare
Valued Member
 
Join Date: Oct 2005
Posts: 247
Default Re: Singleton handles

Quote:
Originally Posted by Reedbeta
there's nothing in the code you showed about controlling destruction order, which can be an issue (though your method does allow construction order to be controlled rather elegantly).
He mentioned lifetime management in the text, though, without having to commit to one approach if he put it in code (a good thing because that's holy war territory)... but what exactly do you think is more elegant about construction with this?
___________________________________________
http://www.iguanademos.com/Jare
Jare is offline   Reply With Quote
Old 12-09-2007, 01:38 PM   #6
Reedbeta
DevMaster Staff
 
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
Default Re: Singleton handles

If singleton B depends on singleton A already having been initialized, you can just instantiate a handle to A in B's constructor (the implementation constructor, not the handle constructor). As long as you have no cycles in your singleton dependency graph, everything will sort itself out and be constructed in the right order and as late as possible (i.e. not till it's actually needed).

Unfortunately there doesn't seem to be quite such an elegant way to make things automatically destruct in the right order. Of course you can always insert explicit deletes at the bottom of main() or something like that, but that seems brittle, since if you add a new singleton or change the dependencies between singletons, you can easily forget to update the deletion code.
___________________________________________
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 12-11-2007, 04:29 AM   #7
bramz
Valued Member
 
Join Date: Aug 2005
Posts: 189
Default Re: Singleton handles

Singletons are just hard. Code that relies too much on singletons runs into problems sooner or later. There are two reasons, a technical one and a ... other one. The technical one is singleton destruction. If singletons start to depend on other singletons, using the naive implementation as above, there's just no way that you will get the order of destruction right. The other one is that what one day seems to be a perfectly valid reason to implement a singleton, turns out to be a situation where you need two instances after all on the other day.

Andrei Alexandrescu has some great solutions for singleton implementations in his book Modern C++ design, solving the former problem with a longevity "register". Also he deals with some multithreading issues (what happens if both threads want to create the singleton instance at the same time?).

For the latter problem, I find one step into the right direction not to design the class as a singleton, but to "use" it as a singleton. J22's SingletonPtr comes close to that idea. Seperate the singleton pattern from the class, so that you can always create more instances of the class if necessary. Of course, that still doesn't solve the issue where you need two seperated "instances" of code that _use_ singletons. Say, you have some code that uses a singleton and one day you want to run the same code on multiple threads, but completely seperated: i.e. they should not use the "same singleton". Then what? There are some ways of course to help the situation. Sometimes you will be able to use the same singleton after all if you add some locking, or you can use Thread Local Storage tricks to have a singleton per thread. But at the end of the day, it's better to design without singletons if it is at all possible.

Cheers,
Bramz
___________________________________________
hi, i'm a signature viruz, plz set me as your signature and help me spread :)
Bramz' warehouse | LiAR isn't a raytracer
bramz is offline   Reply With Quote
Old 12-20-2007, 09:18 PM   #8
TheNut
Senior Member
 
TheNut's Avatar
 
Join Date: Aug 2004
Location: Thornhill, TO
Posts: 850
Default Re: Singleton handles

The thing I don't like about singletons is when you're dealing with DLLs. They have their own memory space, so you can end up with multiple singletons floating around.

I find using factories work quite well in combination with singletons, since factories isolate objects in their own memory space and can guarantee only one instance of it is created.

I also wouldn't worry about deleting singletons. In most cases, the reason you have them is because you only want one instance of it in the entire program. The object could have special flags and other states, so it may be important to keep the singleton alive for the duration of the program even when you're not using it. You could also run into memory access issues if you are dealing with DLL files.
___________________________________________
http://www.nutty.ca - Being a nut has its advantages.
TheNut is offline   Reply With Quote
Old 12-20-2007, 11:28 PM   #9
Reedbeta
DevMaster Staff
 
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
Default Re: Singleton handles

Quote:
Originally Posted by TheNut
I also wouldn't worry about deleting singletons.

It's nice to be able to gracefully cleanup singletons, like closing net connections, closing files, releasing memory and so on. Granted that this isn't *actually* necessary on most modern OSes as the kernel will close files and so forth for you (in most cases). Still, I feel it's a good programming practice.
___________________________________________
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 05-30-2008, 10:18 AM   #10
gasto
New Member
 
gasto's Avatar
 
Join Date: Sep 2005
Location: Rome
Posts: 9
Default Re: Singleton handles

Call me noob, but shouldn't:

Code:
MySingletonImpl* MySingleton::MySingletonImpl = NULL;

actually be:

Code:
MySingletonImpl* MySingleton::instance = NULL;

?
___________________________________________
To live is to be eager to die.
gasto 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 03:25 AM.


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