Elaborate.JohnJ wrote: However I actually agree with nullsquared that global access like this should be avoided if possible. He's absolutely right that use of singletons can be a very bad design, but I disagree that this is true in all cases 100% of the time. My approach to programming is simple: use features with care and common sense. So I acknowledge the fact that in very rare cases singletons (aka global access to variables or functions) is sometimes necessary, and even logical.
Singleton Discussion
- nullsquared
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
Singleton Discussion
Singletons: don't use them. If you need global access, use a global variable. If you need a single instance, then only ever make 1 instance.
- JohnJ
- OGRE Expert User

- Posts: 975
- Joined: Thu Aug 04, 2005 4:14 am
- Location: Santa Clara, California
- x 4
Re: Singleton Discussion
Singletons are by nature a syntactic synonym of global variables and functions under a namespace. So by saying "if you need global access, use a global variable", I don't think you realize that this is the same thing as a singleton.Singletons: don't use them. If you need global access, use a global variable. If you need a single instance, then only ever make 1 instance.
For one: Keyboard device input.Elaborate.
Show me one reason why a keyboard device class would be more cleanly implemented as a non-global access class. I'll keep an open mind.
- nullsquared
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
Re: Singleton Discussion
No. A singleton, as its name implies, is a class that there should only ever be a single instance of. It has nothing to do with global access (which is what global variables are for, which themselves are also bad).JohnJ wrote:Singletons are by nature a syntactic synonym of global variables and functions under a namespace. So by saying "if you need global access, use a global variable", I don't think you realize that this is the same thing as a singleton.Singletons: don't use them. If you need global access, use a global variable. If you need a single instance, then only ever make 1 instance.
Here:For one: Keyboard device input.Elaborate.
Show me one reason why a keyboard device class would be more cleanly implemented as a non-global access class. I'll keep an open mind.
Code: Select all
input::input input(root->hwnd());
input.mouseSens = 0.25;
input.resize(root->width(), root->height());
/* ... */
configure(*root, input, stateMgr, &opts);
// game loop
while(root->windowIsOpen())
{
/* ... */
// capture input
input();
/* ... */
}
/* ... */
- JohnJ
- OGRE Expert User

- Posts: 975
- Joined: Thu Aug 04, 2005 4:14 am
- Location: Santa Clara, California
- x 4
Re: Singleton Discussion
If a singleton has nothing to do with global access, then getSingleton() or equivalent behavior shouldn't even exist - by your definition a pure singleton (without global access) would be nothing more than enforcement code to throw an error when more than once instance is created. That would be absolutely pointless for a number of reasons.No. A singleton, as its name implies, is a class that there should only ever be a single instance of. It has nothing to do with global access (which is what global variables are for, which themselves are also bad).
This is not how Ogre uses singletons, and this is not how I've ever seen singletons used (although I haven't worked with singletons a whole lot outside of Ogre).
First of all, that code is extremely hard to read. I couldn't have given a better illustration myself as proof of my earlier statement of it being better to capitalize class/namespace names:Code: Select all
input::input input(root->hwnd()); input.mouseSens = 0.25; input.resize(root->width(), root->height()); /* ... */ configure(*root, input, stateMgr, &opts); // game loop while(root->windowIsOpen()) { /* ... */ // capture input input(); /* ... */ } /* ... */
Code: Select all
input::input input(root->hwnd());
...
input();But to address whatever you're trying to prove with that code, what does input() do? Is it a functor? Is it a member function within some scope I don't see? What scope is this anyway? To quote from one of your earlier posts:
What happened to self-documenting code?
Last edited by JohnJ on Sat Jul 04, 2009 7:02 pm, edited 2 times in total.
- nullsquared
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
Re: Singleton Discussion
Precisely!JohnJ wrote:If a singleton has nothing to do with global access, then getSingleton() or equivalent behavior shouldn't even exist - by your definition a pure singleton (without global access) would be nothing more than enforcement code to throw an error when more than once instance is created.No. A singleton, as its name implies, is a class that there should only ever be a single instance of. It has nothing to do with global access (which is what global variables are for, which themselves are also bad).
And there you have it, singletons!That would be absolutely pointless for a number of reasons.
Just because Ogre uses them doesn't mean they're good.This is not how Ogre uses singletons, and this is not how I've ever seen singletons used (although I haven't worked with singletons a whole lot outside of Ogre).
Alright, I'll rename it to inputSystem. Same thing.First of all, that code is extremely hard to read. This is a good illustration to evidence my earlier mention of it being better to capitalize class/namespace names:Code: Select all
input::input input(root->hwnd()); input.mouseSens = 0.25; input.resize(root->width(), root->height()); /* ... */ configure(*root, input, stateMgr, &opts); // game loop while(root->windowIsOpen()) { /* ... */ // capture input input(); /* ... */ } /* ... */That has got to be the most ambiguous use of naming I've ever seen. I think you've just removed any chance of your example providing evidence for your method being clean and easy to read.Code: Select all
input::input input(root->hwnd()); ... input();
What does input() do? I think the name is enough. It captures input. It reaches the destination code via the input object itself as well as buffered input callbacks.But to address whatever you're trying to prove with that code, what does input() do? What scope is this? How does the input data reach the code that controls whatever it controls?
- JohnJ
- OGRE Expert User

- Posts: 975
- Joined: Thu Aug 04, 2005 4:14 am
- Location: Santa Clara, California
- x 4
Re: Singleton Discussion
Sorry about the edit again, I made it clearer:What does input() do? I think the name is enough. It captures input. It reaches the destination code via the input object itself as well as buffered input callbacks.
"But to address whatever you're trying to prove with that code, what does input() do? Is it a functor? Is it a member function within some scope I don't see? What scope is this anyway? To quote from one of your earlier posts: 'What happened to self-documenting code?'"
I agree that the singleton concept you defined is completely pointless and a bad idea in pretty much every case I can think of. But I don't think your definition of singleton = Ogre's/my definition of singleton.And there you have it, singletons!
I didn't say that the fact that Ogre uses them makes it ok (in fact I would prefer if Ogre used singletons a lot less). I said that Ogre's use of singletons seems to be different from your definition - in other words the singleton classes could be theoretically rewritten as namespaces containing global variables and functions.Just because Ogre uses them doesn't mean they're good.
Where does it capture it to? Also saying it reaches the destination code "via the input object itself" is very hazy. Once I can decipher your code I'll show you a "static class" implementation (I won't use the word "singleton" to avoid ambiguity) and how much easier it is to read (IMO anyway).What does input() do? I think the name is enough. It captures input. It reaches the destination code via the input object itself as well as buffered input callbacks.
- nullsquared
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
Re: Singleton Discussion
It doesn't matter whether it's a functor or a member function. That's an encapsulation detail. What is important is the fact that it does input.JohnJ wrote: "But to address whatever you're trying to prove with that code, what does input() do? Is it a functor? Is it a member function within some scope I don't see? What scope is this anyway? To quote from one of your earlier posts: 'What happened to self-documenting code?'"
It doesn't matter. Once again, encapsulation.Where does it capture it to?What does input() do? I think the name is enough. It captures input. It reaches the destination code via the input object itself as well as buffered input callbacks.
Notice the configure() function. Whatever needs input will get a reference to the input object.Also saying it reaches the destination code "via the input object itself" is very hazy.
Why? It won't help at all, the current code works great as it is. Why bother with a "static class?"Once I can decipher your code I'll show you a "static class" implementation (I won't use the word "singleton" to avoid ambiguity) and how it helps.
- JohnJ
- OGRE Expert User

- Posts: 975
- Joined: Thu Aug 04, 2005 4:14 am
- Location: Santa Clara, California
- x 4
Re: Singleton Discussion
Your view of encapsulation is wrong. Knowing that it "does" input isn't enough, "do" can include capturing, processing, applying, or halting program execution with a prompt. You function name should be "captureInput();" if this is what it does.It doesn't matter whether it's a functor or a member function. That's an encapsulation detail. What is important is the fact that it does input.
Again, extremely vague. I hope you don't think encapsulation means you should be vague, because this is very bad practice. "configure()" can mean many different things. At a glance, I have no idea what that configure call is configuring. I'm not saying your code is unstructured, just that it's far from self-documenting.Notice the configure() function. Whatever needs input will get a reference to the input object.
When I first began programming I wrote spaghetti code that "worked great as is", but that doesn't make it a good design.Why? It won't help at all, the current code works great as it is. Why bother with a "static class?"
- _tommo_
- Gnoll
- Posts: 677
- Joined: Tue Sep 19, 2006 6:09 pm
- x 5
- Contact:
Re: Singleton Discussion
I think that the whole discussion boils down to one thing:
OOP is not always enough.
So, there are problems where the "OOP laws" are actually an obstacle, and have to be ignored, so i don't agree completely with nullsquared. For example all the cases when you do know you need one and only one instance of something, etc (memory allocators, default log, filesystem managers)
Obviously, one must be careful in deciding when to ignore the OOP guidelines, as you could have a problem later
Like when you do realize that one and only one instance was not enough
Anyway i try to avoid as much as possible to use singletons, if carefully designed you don't have to overload constructors with parameter
Ideally, one object should be able to retrieve all its needed informations from its direct creator... when that isn't the case a Singleton could be in order.
OOP is not always enough.
So, there are problems where the "OOP laws" are actually an obstacle, and have to be ignored, so i don't agree completely with nullsquared. For example all the cases when you do know you need one and only one instance of something, etc (memory allocators, default log, filesystem managers)
Obviously, one must be careful in deciding when to ignore the OOP guidelines, as you could have a problem later
Like when you do realize that one and only one instance was not enough
Anyway i try to avoid as much as possible to use singletons, if carefully designed you don't have to overload constructors with parameter
Ideally, one object should be able to retrieve all its needed informations from its direct creator... when that isn't the case a Singleton could be in order.
- xavier
- OGRE Retired Moderator

- Posts: 9481
- Joined: Fri Feb 18, 2005 2:03 am
- Location: Dublin, CA, US
- x 22
Re: Singleton Discussion
I think too much attention is paid to the name (which is an entirely different discussion, one regarding the elevation of "design patterns" to first-class status).
Regardless, this particular focus on "object purity" always comes up at a certain point in one's evolution as a software engineer. At some point you get over the rigidity of this "doctrine", usually when you realize that blind adherence to this particular "principle" actually gets in the way of productivity.
You use whatever construct you need to do the job. No more, no less. If a "singleton" fits the needs, you use that construct. If you don't need a "singleton", you don't. Having any sort of immutable law that ever precludes doing things different, is an obstacle in itself.
Selah.
Regardless, this particular focus on "object purity" always comes up at a certain point in one's evolution as a software engineer. At some point you get over the rigidity of this "doctrine", usually when you realize that blind adherence to this particular "principle" actually gets in the way of productivity.
You use whatever construct you need to do the job. No more, no less. If a "singleton" fits the needs, you use that construct. If you don't need a "singleton", you don't. Having any sort of immutable law that ever precludes doing things different, is an obstacle in itself.
Selah.
- JohnJ
- OGRE Expert User

- Posts: 975
- Joined: Thu Aug 04, 2005 4:14 am
- Location: Santa Clara, California
- x 4
Re: Singleton Discussion
Exactly.
This is the same thing I tried to explain in the other thread but you explained it much better than I did:
(From an entirely abstract logical point of view, that statement is inherently non-factual. It's based largely on an opinion or personal experience that was incorrectly promoted to an overly broad factual assertion)
This is the same thing I tried to explain in the other thread but you explained it much better than I did:
Also, something I almost forgot:I wrote:My approach to programming is simple: use features with care and common sense. So I acknowledge the fact that in very rare cases singletons (aka global access to variables or functions) is sometimes necessary, and even logical.
I would like to suggest to nullsquared, with respect, that statements like this be used with extreme caution. I don't know how old you are, but you should be aware that the more you know, the more you know there's even more that you don't know; statements like these risk being interpreted as either arrogance or a naive overconfidence typically associated with teenagers - I'm not assuming you are one so forgive me if this sounds like an insult; I'm merely suggesting that statements like these be phrased carefully to do yourself justice. I'm certainly not blameless myself in this regard, and have on more than one occasion made the same mistake, so I'm not blaming you.nullsquared wrote:It was already done. There are no arguments for using singletons, they can all be countered, and in the end, singletons are not to be used, period.
(From an entirely abstract logical point of view, that statement is inherently non-factual. It's based largely on an opinion or personal experience that was incorrectly promoted to an overly broad factual assertion)
- JohnJ
- OGRE Expert User

- Posts: 975
- Joined: Thu Aug 04, 2005 4:14 am
- Location: Santa Clara, California
- x 4
Re: Singleton Discussion
First, it's not a "bother" - in most cases it's easier to do a "static class". The problem in fact is usually to be careful not to be lazy and make too many things static/global when they shouldn't be, not the other way around.Why bother with a "static class?"
In the case of the keyboard example, I would ask, "why not?" Just hypothetically, if both methods were equally easy to use, which would make more sense when dealing with a purely singular object like a keyboard? Something to think about, anyway.
Here's another issue that singletons can help solve: Generally classes should be designed to be as self-contained as possible. This means to avoid references to "parent" classes as well as lateral class references whenever possible. Sometimes you can get into situations where accessing an inherently singular data object is necessary from multiple levels of your code, and storing 100 local references to this object across your code or multiple parent dereferences to resolve to the desired object becomes tedious and error prone. In this case, often the cleanest and most elegant solution is a global/static/singleton implementation of some sort.
Another reason to use them is it's just more convenient and productive in some cases. Again, singletons should be used with caution, but there are definitely cases where it makes programming easier without sacrificing functionality or clean design.
Last edited by JohnJ on Sat Jul 04, 2009 9:44 pm, edited 1 time in total.
- jacmoe
- OGRE Retired Moderator

- Posts: 20570
- Joined: Thu Jan 22, 2004 10:13 am
- Location: Denmark
- x 179
- Contact:
Re: Singleton Discussion
I prefer a singleton over a plain old global.
And a singleton helps with ownership issues, often seen in global classes. (Like a logmanager). Because of it singularity.
Static utility classes are great, but not really comparable to singletons. They are like carrots and bananas.
And a singleton helps with ownership issues, often seen in global classes. (Like a logmanager). Because of it singularity.
Static utility classes are great, but not really comparable to singletons. They are like carrots and bananas.
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
-
CABAListic
- OGRE Retired Team Member

- Posts: 2903
- Joined: Thu Jan 18, 2007 2:48 pm
- x 58
- Contact:
Re: Singleton Discussion
@nullsquared: Since you always plead for injection over singletons, I'd like to ask you (and I'm serious, I'm not trying to tease you or anything) how you would solve the following situation? Suppose that Ogre were not using singletons. Apparently though there would still be a ResourceGroupManager which you'll probably have dealings with in your user code. Now, how do you access it? After all, the ResourceGroupManager is not created by your own code, so you do have to request it from Ogre at some point. Which means that Ogre needs to expose the pointer. Which means that, without singletons, you need a function in Ogre::Root. Which means that Ogre::Root's interface is going to change whenever a new manager is added to Ogre. Which may result in additional recompilations of your code segments.
Granted, this may not be too much of an issue because any such change to Ogre may likely trigger a recompile of your project, anyway. But still I'd be interested how (if at all) you'd solve that in principle.
Also, I would like to say that I really think a logsystem benefits from being implemented as a (self-constructing) singleton. That way you can simply start using it in your code without ever having to worry about where to construct it; it just works when needed, at least basic console output.
Granted, this may not be too much of an issue because any such change to Ogre may likely trigger a recompile of your project, anyway. But still I'd be interested how (if at all) you'd solve that in principle.
Also, I would like to say that I really think a logsystem benefits from being implemented as a (self-constructing) singleton. That way you can simply start using it in your code without ever having to worry about where to construct it; it just works when needed, at least basic console output.
- nullsquared
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
Re: Singleton Discussion
First of all, get rid of ResourceGroupManager. Ogre handles resources in these "resource groups" awfully in my opinion. And I'm sure others will agree. After all, that's what the whole refactoring things is about in 1.8/2.0.CABAListic wrote:@nullsquared: Since you always plead for injection over singletons, I'd like to ask you (and I'm serious, I'm not trying to tease you or anything) how you would solve the following situation? Suppose that Ogre were not using singletons. Apparently though there would still be a ResourceGroupManager which you'll probably have dealings with in your user code. Now, how do you access it? After all, the ResourceGroupManager is not created by your own code, so you do have to request it from Ogre at some point. Which means that Ogre needs to expose the pointer. Which means that, without singletons, you need a function in Ogre::Root. Which means that Ogre::Root's interface is going to change whenever a new manager is added to Ogre. Which may result in additional recompilations of your code segments.
Granted, this may not be too much of an issue because any such change to Ogre may likely trigger a recompile of your project, anyway. But still I'd be interested how (if at all) you'd solve that in principle.
Second, until then you use:
Root::getTextureManager()
Root::getMeshManager()
(interfaces would be needed for the other managers
Root::addResourceLocation
What is wrong with this?Also, I would like to say that I really think a logsystem benefits from being implemented as a (self-constructing) singleton. That way you can simply start using it in your code without ever having to worry about where to construct it; it just works when needed, at least basic console output.
Code: Select all
std::clog << "logging stuff, yay!";
Code: Select all
class logger { ... };
// .hpp
extern logger log;
// .cpp
logger log;
// elsewhere
log << "logging stuff, yay!";
So, basically, you agree that my method is perfectly fine, you're just too stubborn to also agree that your method is not necessary and not preferred?JohnJ wrote: In the case of the keyboard example, I would ask, "why not?" Just hypothetically, if both methods were equally easy to use, which would make more sense when dealing with a purely singular object like a keyboard? Something to think about, anyway.
Tell me, what happens when you want to simulate the input (not perfect example, but an example none-the-less)? In my case, simple.
Code: Select all
//input::input input(...);
// use simulated input, instead
input::simulatedInput input(...); // tada. everything Just Works
Data flow goes down, not up. Why would you need references to parent classes? (other than an object hierarchy, like a GUI, of course)Here's another issue that singletons can help solve: Generally classes should be designed to be as self-contained as possible. This means to avoid references to "parent" classes as well as lateral class references whenever possible. Sometimes you can get into situations where accessing an inherently singular data object is necessary from multiple levels of your code, and storing 100 local references to this object across your code or multiple parent dereferences to resolve to the desired object becomes tedious and error prone. In this case, often the cleanest and most elegant solution is a global/static/singleton implementation of some sort.
100 local references? No:
Code: Select all
class body
{
private:
world &_world; // body needs a reference to the world it's in for whatever reason
public:
body(world &w): _world(w) { ... }
};
You haven't actually provided a concrete example where singletons > not singletons. Just words and theories that are incorrect.Another reason to use them is it's just more convenient and productive in some cases. Again, singletons should be used with caution, but there are definitely cases where it makes programming easier without sacrificing functionality or clean design.
I'm almost 16. And I make statements like that because I can back them up. You've still failed to provide an actual, concrete example where singletons > not singletons.I would like to suggest to nullsquared, with respect, that statements like this be used with extreme caution. I don't know how old you are, but you should be aware that the more you know, the more you know there's even more that you don't know; statements like these risk being interpreted as either arrogance or a naive overconfidence typically associated with teenagers - I'm not assuming you are one so forgive me if this sounds like an insult; I'm merely suggesting that statements like these be phrased carefully to do yourself justice. I'm certainly not blameless myself in this regard, and have on more than one occasion made the same mistake, so I'm not blaming you.
Input is cause, stuff happening is effect. Processing, applying, or halting program execution with a prompt are all effect. Input does not care about effect, as it is the cause. The only thing it does (and, well, the only thing it can do) is capture input.Your view of encapsulation is wrong. Knowing that it "does" input isn't enough, "do" can include capturing, processing, applying, or halting program execution with a prompt. You function name should be "captureInput();" if this is what it does.
Again, extremely vague. I hope you don't think encapsulation means you should be vague, because this is very bad practice. "configure()" can mean many different things. At a glance, I have no idea what that configure call is configuring. I'm not saying your code is unstructured, just that it's far from self-documenting.
Of course you're not gonna know what configure() is, there is no context to my snippet.Wikipedia wrote: Encapsulation is the hiding of information in order to ensure that data structures and operators are used as intended and to make the usage model more obvious to the developer.
-
mirlix
- Goblin
- Posts: 225
- Joined: Mon May 01, 2006 12:03 am
- Location: Germany
- x 5
Re: Singleton Discussion
My point of view is that singletons should only be used when you want to enforce that only one instance of this object should exists. Singletons shouldnt be used as global variables or to avoid passing pointers, this can actual be pretty harmful to your code. Singletons are fine if there is a concrete reason that only one instance of an class should exists. This can be the case for networking or data ports when accessing a connected computer,gadget or anything else would produce errors. If this unusual case crosses your way, then you should use singletons, to be sure there is only one instance. It wouldnt be enough to just make sure that you dont create two instance, you have to make it impossible, because otherwise debugging might be hell. Also try to make something that shouldnt be done impossible rather then advice in comments that it shouldnt be done. It will help you and your fellow programmes a lot
Just my two cents
Just my two cents
- nullsquared
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
Re: Singleton Discussion
Excellent point.mirlix wrote:My point of view is that singletons should only be used when you want to enforce that only one instance of this object should exists. Singletons shouldnt be used as global variables or to avoid passing pointers, this can actual be pretty harmful to your code.
Code: Select all
class willErrorIfMoreThanOne
{
public:
willErrorIfMoreThanOne()
{
static bool alreadyExists = false;
assert(!alreadyExists && "make ONLY ONE of this class");
alreadyExists = true;
}
};
-
mirlix
- Goblin
- Posts: 225
- Joined: Mon May 01, 2006 12:03 am
- Location: Germany
- x 5
Re: Singleton Discussion
Code: Select all
class willErrorIfMoreThanOne
{
public:
willErrorIfMoreThanOne()
{
static bool alreadyExists = false;
assert(!alreadyExists && "make ONLY ONE of this class");
alreadyExists = true;
}
};
- nullsquared
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
Re: Singleton Discussion
Why not? Whoever makes it will give it to others to use.mirlix wrote: Because if there is already one instance of this class there is no possibility to get access to this instance.
Code: Select all
void foo(thereShouldOnlyBeOne &bar)
{
bar.doImportantStuff();
}
int main()
{
thereShouldOnlyBeOne instance;
foo(instance);
}
-
mirlix
- Goblin
- Posts: 225
- Joined: Mon May 01, 2006 12:03 am
- Location: Germany
- x 5
Re: Singleton Discussion
The problem I see with this approach is that it only shifts the possibility of an error. Now you cant get an error because two instances exist, but you cant get an error when you try to create a second instance. And when more then one people work on the project the possibility if very high that someone somewhere will try to create a second instance and it might even happen that this person creates the second instance before you create your first instance. Now your code reports an error because someone else did something wrong in a totally different place. This can get really ugly.
As a fan of defensive programming I would say, dont shift the error, prevent it. In this case one possibility to prevent the error is to make the constructor private and have a getInstance() method. Of course there are others way to achieve this, but I dont know any which works equally well then getInstance(). But I would be delighted to hear some other ideas to solve this problem.
As a fan of defensive programming I would say, dont shift the error, prevent it. In this case one possibility to prevent the error is to make the constructor private and have a getInstance() method. Of course there are others way to achieve this, but I dont know any which works equally well then getInstance(). But I would be delighted to hear some other ideas to solve this problem.
-
CABAListic
- OGRE Retired Team Member

- Posts: 2903
- Joined: Thu Jan 18, 2007 2:48 pm
- x 58
- Contact:
Re: Singleton Discussion
Apparently RGM was just one example of many, but I assume from this that you wouldn't address the issue. Fair enough.nullsquared wrote: First of all, get rid of ResourceGroupManager. Ogre handles resources in these "resource groups" awfully in my opinion. And I'm sure others will agree. After all, that's what the whole refactoring things is about in 1.8/2.0.
Second, until then you use:
Root::getTextureManager()
Root::getMeshManager()
(interfaces would be needed for the other managers
Root::addResourceLocation
It is unformatted. It has no automatic timestamp, for instance. Granted you might not need that for a console output, but I would imagine you normally do have a higher level logsystem which routes formatted output to multiple targets (console, file). My system initialises console logging upon first use of the logging system for early failures and adds file logging later on.What is wrong with this?Code: Select all
std::clog << "logging stuff, yay!";
This is fine until you require another global which might want to log some stuff during construction. Since the order of creation is undefined for global variables, it's bound to fail. I agree that this should be avoided, but the Meyers Singleton is in fact equivalent to such a global, just without the order of initialisation problem, so in that case it has the edge over a simple variable.Code: Select all
And if you [b]really[/b] need your own class for it: [code] class logger { ... }; // .hpp extern logger log; // .cpp logger log; // elsewhere log << "logging stuff, yay!";
- _tommo_
- Gnoll
- Posts: 677
- Joined: Tue Sep 19, 2006 6:09 pm
- x 5
- Contact:
Re: Singleton Discussion
This has no point, because, if one makes it and is the only one that gives it to others, what you made has no point.nullsquared wrote: Why not? Whoever makes it will give it to others to use.
You could just check for existency in the "request creation" method as the instance is not public...
and this is what get methods and factories are for.
- nullsquared
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
Re: Singleton Discussion
What? There is only one instance. Whatever needs to access that instance will receive a reference to it. There is no room for error, because the instance will be only created in one spot.mirlix wrote:Now you cant get an error because two instances exist, but you cant get an error when you try to create a second instance
I smell design issues. Not only is it a global, but it is a global with a non-trivial constructor that needs to log something?CABAListic wrote: This is fine until you require another global which might want to log some stuff during construction.
What? You will simply use dependency injection. If something needs it, it will get a reference to it._tommo_ wrote: This has no point, because, if one makes it and is the only one that gives it to others, what you made has no point.
- JohnJ
- OGRE Expert User

- Posts: 975
- Joined: Thu Aug 04, 2005 4:14 am
- Location: Santa Clara, California
- x 4
Re: Singleton Discussion
That's almost exactly how my singleton implementation works, but mine is a little more flexible with construction. After seeing this, I'm starting to think the main disagreement between you/me on this is simply due to an inconsistency of the definition of "singleton".And if you really need your own class for it:Code: Select all
class logger { ... }; // .hpp extern logger log; // .cpp logger log; // elsewhere log << "logging stuff, yay!";
Apparently we have an inconsistency of naming here. To me, "singleton" = "global class". To you, "singleton" = "debug assertion" (basically). I think the latter is a bad idea because a debug assertion does nothing to resolve the root problem, just defers it to another area of code.Singletons shouldnt be used as global variables or to avoid passing pointers, this can actual be pretty harmful to your code. Singletons are fine if there is a concrete reason that only one instance of an class should exists. This can be the case for networking or data ports when accessing a connected computer,gadget or anything else would produce errors. If this unusual case crosses your way, then you should use singletons, to be sure there is only one instance.
ExactlyAs a fan of defensive programming I would say, dont shift the error, prevent it.
If anything, I'm usually one of the first to mention that singletons are most definitely not necessary and in most cases not preferred. But I also accept the fact that there are (rare) cases where to singletons are in fact preferred. Although you've tried, you can't deny this. You can only try argue that every programmer in the world is wrong who makes the choice to use a singleton over whatever alternates there are, and this, needless to say, is going to be a losing battle.So, basically, you agree that my method is perfectly fine, you're just too stubborn to also agree that your method is not necessary and not preferred?
As to whether your code is "perfectly fine" or not, I can't really tell because I don't know enough about it to say reliably, but from what I've seen it's pretty ambiguous and difficult to read in general, so no, I never said I agree that your method is perfectly fine.
My point was "input" is a vague verb, and is therefore ambiguous in many cases. You're little code example proves this very nicely:Input is cause, stuff happening is effect. Processing, applying, or halting program execution with a prompt are all effect. Input does not care about effect, as it is the cause. The only thing it does (and, well, the only thing it can do) is capture input.
Code: Select all
input::input input();
input();I'm referring to object hierarchy, as in a game object storing a number of pointers to manager objects above it.Data flow goes down, not up. Why would you need references to parent classes? (other than an object hierarchy, like a GUI, of course)
In the case of the code you posted, it looks like it's more likely to be problematic with chains of backward dereferences, like "body.world.root.input.keyboard.isKeyDown()" (just an example). Rather than "Keyboard->isKeyDown()". I'll assume for now that I don't need to explain why the former is horrible design, but let me know if you need me to explain it. Now I'm not saying you have a problem like this, but that it's my best guess as to where a singleton could help, considering I don't know much about the rest of your code.100 local references? No:1 reference. Not 100.Code: Select all
class body { private: world &_world; // body needs a reference to the world it's in for whatever reason public: body(world &w): _world(w) { ... } };
It's not about me, I don't have to prove anything to you. I think you don't understand the implication of your statement that "singletons are not to be used, period". You can't possibly back this up; it's logically an impossibility. To spell it out for you: you're basically saying that every programmer in the history of mankind who has ever used a singleton over the alternative was making the wrong decision. Good luck "backing that up".And I make statements like that because I can back them up. You've still failed to provide an actual, concrete example where singletons > not singletons.
Once that is understood, I'll point out that there are plenty of concrete examples where singletons > not singletons, all you have to do is open your eyes to them. You've even posted some yourself. "std::clog", for example, is just as much a singleton as "Ogre::LogManager::getSingleton()" for all practical purposes.
To be perfectly honest I don't like arguing for singletons, because I don't like them in most cases anyway. I already gave you the example of the keyboard class. I could type up a long code example demonstrating exactly why it's advantageous, but at this point I've wasted enough time already on this thread.You haven't actually provided a concrete example where singletons > not singletons. Just words and theories that are incorrect.
But I really need to learn to stay out of pointless flamewars like these in the first place. I should have known better.
- steven
- Gnoll
- Posts: 657
- Joined: Mon Feb 28, 2005 1:53 pm
- Location: Australia - Canberra (ex - Switzerland - Geneva)
- Contact:
Re: Singleton Discussion
I don't see why I would need more than one EngineManger, GraphicsManager, LogManager, NetworkManager, InputManager and some others.
So why should I bother to pass references or pointers everywhere and not simply access them via singleton?
It makes lots of constructors and methods simpler.
So why should I bother to pass references or pointers everywhere and not simply access them via singleton?
It makes lots of constructors and methods simpler.
