Page 2 of 4

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 10:14 am
by mirlix
nullsquared wrote:
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
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.
What I mean is that your program will terminate when the following happens

Code: Select all

int main()
{
    thereShouldOnlyBeOne instance;
    thereShouldOnlyBeOne instance2;//Here the program dies

    foo(instance);
}
In this case the error is easy to find, but it could be in totally different totally unrelated code files, then it gets tricky. And even worse, like stated before, you can have correct code which works without an error. Now comes a second programmer along who creates some code which is run before your code and there he create an instance of this class. Now your code fails without an error in your code. In my opinion it would be better to use the following technique. Because your approach doesnt prevent the error of two instance existing, it only shifts the point when the error occurs.

Code: Select all

int main()
{
    thereShouldOnlyBeOne* instance =     thereShouldOnlyBeOne::getSingleton():
    thereShouldOnlyBeOne* instance2 = thereShouldOnlyBeOne::getSingleton():;//Here the program doesnt die but instance2 == instance

    foo(instance);
}
JohnJ wrote: 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.
Not excatly. My target with the getInstance() method would be that no error occurs, you simply get always the same instance when calling the method. This would solve the problem of two instances existing at the same time. I cant disagree that a singleton is always a global class, but this shouldnt be the reason for making a singleton, sometimes you have to but quite often there is another way.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 10:59 am
by syedhs
steven wrote: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.
Yes I agree with you - it all boils down to practicality. All those 'religious' issues like 'never use singleton' and followed by technical explanation which isn't really understood should not be accepted. I really think the conundrum of having singleton (or not) will only arise once your project becomes large enough and in most cases, can be managed if you know what you are doing.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 11:16 am
by CABAListic
nullsquared wrote: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?
So, next thing you're going to tell me that you have never, ever inserted a log statement inside a constructor, not even temporarily for debug purposes? Heh, I swear you must be the god of infallible software design.
In any case, the point is that a Meyers singleton is in fact nothing else but a global variable minus the mentioned order of creation problem and an added implicit (no runtime errors) ensurance that you are only ever using the single instance of it. So tell me again, what makes your global variable better for the log system?

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 1:33 pm
by nullsquared
CABAListic wrote:
nullsquared wrote: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?
So, next thing you're going to tell me that you have never, ever inserted a log statement inside a constructor, not even temporarily for debug purposes?
In a constructor, yes. Not in a global variable's constructor.
So tell me again, what makes your global variable better for the log system?
I can create as many of it as I want. I can even create derived types (such as, you know, std::ofstream ;))
JohnJ wrote:
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!";
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".
Perhaps. What you're talking about is not a singleton. That is simply a global variable. Nothing to do with singletons.
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.
My point was "input" is a vague verb, and is therefore ambiguous in many cases. You're little code example proves this very nicely:

Code: Select all

input::input input(...);
input();
Not exactly self documenting.
Alright, so my input class is named a bit ambiguously because its namespace is also named input. But you can't just mash those parts together like that - they have a context (one which I cut out so I can only show you the input part - imagine there's more to it in the /* ... */ blocks).
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.
No. Once again, I smell design issues.

body is a physics body class. The world is the physics world class (they'e both in the phys namespace). The body might need to know about it's world, for example, to be created properly (for example, when I use Newton, to create a body, you need to pass the World it is created within). It does NOT need to know anything about keyboards, input, roots, etc. Give me a better example for your "reference chaining" and I'll show you how I don't have that problem.
You've even posted some yourself. "std::clog", for example, is just as much a singleton as "Ogre::LogManager::getSingleton()" for all practical purposes.
No. I can create as many ostreams (or types derived from ostreams) as I want. std::clog is simply a global.
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.
Well then instead of wasting your time on telling me about the "keyboard example," you should've simply shown me the "keyboard example." Besides my ambiguous naming, my method is perfectly fine. Look at it this way if you really can't get past the simple naming:

Code: Select all

engine::input::inputSystem input(root->hwnd());

while (...)
{
    ...
    input();
    ...
}
No singletons. No globals. No need.
steven wrote: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.
I'll assume that your GraphicsManager is the equivalent of my renderer (handles the graphics and actual rendering).

In my game, you'll be able to have in-game computers. These in-game computers can render scenes from the game (like a camera). In my non-singleton case, I can simply create a second renderer specifically for the in-game computer, and done:

Code: Select all

computer::computer()
{
    // create our own scene manager so that the scene doesn't conflict with the game's scene
    _sceneMgr = ...;

    _renderer.reset(new forwardRenderer(_screen.viewport(), _sceneMgr));
}

void computer::tick(...)
{
    _renderer.render(); // render to our screen
}
Since my entity manager (aka my game::world) is also not a singleton, my in-game computer can start spawning its own entities in its own little world, etc.
mirlix wrote: Not excatly. My target with the getInstance() method would be that no error occurs, you simply get always the same instance when calling the method. This would solve the problem of two instances existing at the same time. I cant disagree that a singleton is always a global class, but this shouldnt be the reason for making a singleton, sometimes you have to but quite often there is another way.
I see what you're saying. What about, perhaps:

Code: Select all

// instead of thereShouldOnlyBeOne, I'll call it foo this time to be easy
class foo
{
    private:
        foo();
        foo(const foo&);
        foo &operator=(const foo&);

        friend foo &createFooImpl(const char *file, const char *func, unsigned line);
};

foo &createFooImpl(const char *file, const char *func, unsigned line)
{
    static bool alreadyExists = false;
    if (alreadyExists)
    {
        std::cerr << "created second foo in " << file << " in " << func " on line " << line;
        assert(false && "create only one foo");
    }
    static foo theFoo;
    return theFoo;
}

#define createFoo() createFooImpl(__FILE__, __FUNCTION__, __LINE__)

void bar(foo &ourFoo)
{
    foo theFoo; // compiler error
    foo &theFoo2 = createFoo(); // "created second foo in main.cpp in void bar(foo &ourFoo) on line 123" <assert>
}

int main()
{
    foo &ourFoo = createFoo();

    bar(ourFoo);
}
This way you find the issue, instead of simply avoiding it.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 2:47 pm
by CABAListic
nullsquared wrote: I can create as many of it as I want. I can even create derived types (such as, you know, std::ofstream ;))
But that's the point: You are not supposed to. You keep comparing a log system to std::clog, but seriously, any sophisticated log system is more than a primitive output (and clog is nothing more). Most log systems I know have timestamps, log levels, whatever. They probably also need to deal with serialising access in multi-threaded applications.
Nothing of which clog provides.
If you create two instances of your log system, both of which happen to output to the console (or to the same file, for that matter), you bypass the thread serialisation. And this is an error. The singleton prevents the error.
(Technically speaking, the console output part of your log system is the one that needs to exist only once. A higher-level log target which routes log messages to one or several outputs could be instantiated multiple times if you desire. But that's irrelevant for the argument).

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 2:51 pm
by mirlix
nullsquared wrote:This way you find the issue, instead of simply avoiding it.
I dont want to find the issue, I want to prevent it from happing. The point of my singleton idea is to be sure there is only one instance and everybody who needs to use the class gets the same instance. Nothing more and nothing less. Simply printing an error message doenst help making a program more robust, prevent the misuse does :)

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 3:18 pm
by nullsquared
CABAListic wrote:Nothing of which clog provides.
Really?

http://www.gamedev.net/reference/snippe ... ogSnippet/

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 3:32 pm
by JohnJ
No. I can create as many ostreams (or types derived from ostreams) as I want. std::clog is simply a global.
Tell me, how many std::clogs are there at once? Two? Five? Oh wait... there's only ever one. "I smell" a Singleton :)
No. Once again, I smell design issues.
That was my whole point.
body is a physics body class. The world is the physics world class (they'e both in the phys namespace). The body might need to know about it's world, for example, to be created properly (for example, when I use Newton, to create a body, you need to pass the World it is created within). It does NOT need to know anything about keyboards, input, roots, etc. Give me a better example for your "reference chaining" and I'll show you how I don't have that problem.
I didn't say you had this problem, I said this is one of the types of common problems singletons can provide a cleaner solution to in rare cases. I can't provide you a better example, you're essentially asking me to find a problem with your code without even seeing your code.

Code: Select all

engine::input::inputSystem input(root->hwnd());

while (...)
{
    ...
    input();
    ...
}
This is just as bad. Again, what is input();? What scope is this? I need to know how input() or whatever accesses the input system object before I can give you an example of how a global/singleton would improve this.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 3:44 pm
by CABAListic
nullsquared wrote:
CABAListic wrote:Nothing of which clog provides.
Really?

http://www.gamedev.net/reference/snippe ... ogSnippet/
Yes, really. What they do there is nothing other than implement those missing features, because clog does not provide any of them. That they redirect clog to their implementation instead of building an implementation on top of clog or cout is a design choice and irrelevant to the argument. Besides, it needs explicit setup at the start of your program, whereas my log system does not. In that regard, my approach is friendlier for reuse ;)

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 3:46 pm
by nullsquared
JohnJ wrote:
No. I can create as many ostreams (or types derived from ostreams) as I want. std::clog is simply a global.
Tell me, how many std::clogs are there at once? Two? Five? Oh wait... there's only ever one. "I smell" a Singleton :)
A singleton is a class type of which there can only exist one of. std::clog is a global, not a singleton.
body is a physics body class. The world is the physics world class (they'e both in the phys namespace). The body might need to know about it's world, for example, to be created properly (for example, when I use Newton, to create a body, you need to pass the World it is created within). It does NOT need to know anything about keyboards, input, roots, etc. Give me a better example for your "reference chaining" and I'll show you how I don't have that problem.
I didn't say you had this problem, I said this is one of the types of common problems singletons can provide a cleaner solution to in rare cases.
Nope, this is a common problem that should have some refactoring done. Simply falling back to a singleton/globals is avoiding the issue, not fixing it.

Code: Select all

engine::input::inputSystem input(root->hwnd());

while (...)
{
    ...
    input();
    ...
}
This is just as bad. Again, what is input();? What scope is this? I need to know how input() or whatever accesses the input system object before I can give you an example of how a global/singleton would improve this.
Like I said, it doesn't matter. input() does ... well, input. That's all you need to know at the current level of code (program flow goes like this: input -> logic -> render, repeat; this is exactly what I've done at this level of code). What it does under the hood is an implementation detail which is encapsulated. This just further proves that a singleton/global would be useless here.

Also, did you completely miss my example?
nullsquared wrote: 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

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 3:47 pm
by nullsquared
CABAListic wrote:
nullsquared wrote:
CABAListic wrote:Nothing of which clog provides.
Really?

http://www.gamedev.net/reference/snippe ... ogSnippet/
Yes, really. What they do there is nothing other than implement those missing features, because clog does not provide any of them. That they redirect clog to their implementation instead of building an implementation on top of clog or cout is a design choice and irrelevant to the argument. Besides, it needs explicit setup at the start of your program, whereas my log system does not. In that regard, my approach is friendlier for reuse ;)
Um. OK, but I still fail to see why this warrants a singleton.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 3:52 pm
by CABAListic
*sigh* As I said, thread synchronisation only works if there's only ever one instance of whichever class does the synchronisation. Which is exactly what a singleton ensures.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 3:57 pm
by nullsquared
CABAListic wrote:*sigh* As I said, thread synchronisation only works if there's only ever one instance of whichever class does the synchronisation. Which is exactly what a singleton ensures.
You can synchronise it that way using a simple global, too (for example, my link does synchronisation via std::clog). Like I said, it does not warrant a singleton.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 4:21 pm
by JohnJ
In my game, you'll be able to have in-game computers. These in-game computers can render scenes from the game (like a camera). In my non-singleton case, I can simply create a second renderer specifically for the in-game computer, and done
You need to create an entirely new render system object to render multiple camera views? "I smell design issues."
That is simply a global variable. Nothing to do with singletons.
How many global variables called "clog" do you have?

Here is a code example that might help nullsquared understand the use of singletons and their practical equivalence to globals, or for anyone else who can't understand it in abstract and needs a practical example:

Without singleton/global:

Code: Select all

class PhysicsBody
{
    World *world;
    ...
    void someFunction()
    {
        ...
        //Error!
        world->getRenderer()->getRoot()->getLogger() << "Error message!";
    }
    ...
}
With singleton/global:

Code: Select all

class PhysicsBody
{
    World *world;
    ...
    void someFunction()
    {
        ...
        //Error!
        Log.getSingleton() << "Error message!";
        //OR
        std::clog << "Error message!";
    }
    ...
}
If you don't see the practical equivalence of a singleton to a global variable here, then you either "just doesn't get it", or are arguing for the sake of arguing.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 5:08 pm
by nullsquared
JohnJ wrote:
In my game, you'll be able to have in-game computers. These in-game computers can render scenes from the game (like a camera). In my non-singleton case, I can simply create a second renderer specifically for the in-game computer, and done
You need to create an entirely new render system object to render multiple camera views? "I smell design issues."
Render system? gfx::renderer has nothing to do with Ogre::RenderSystem. It is what its name implies - a renderer. It abstracts away rendering (for example, I have both a forwardRenderer and a deferredRenderer - the main game can use one, but an in-game computer can use the other).
That is simply a global variable. Nothing to do with singletons.
How many global variables called "clog" do you have?
Image
Wikipedia wrote: In software engineering, the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object.
Why are you so stubborn to acknowledge that std::clog is NOT a singleton, but a GLOBAL? And you're calling me the stubborn teenager.
Here is a code example that might help nullsquared understand the use of singletons and their practical equivalence to globals, or for anyone else who can't understand it in abstract and needs a practical example:

Without singleton/global:

Code: Select all

class PhysicsBody
{
    World *world;
    ...
    void someFunction()
    {
        ...
        //Error!
        world->getRenderer()->getRoot()->getLogger() << "Error message!";
    }
    ...
}
No. Without global:

Code: Select all

class PhysicsBody
{
    World &world;
    Logger &log;

    // disregarding the fact that you made this all under private:
    PhysicsBody(World &world, Logger &log): world(world), log(log) {}

    ...
    void someFunction()
    {
        ...
        //Error!
        log << "Error message!";
    }
    ...
}
But, of course, that's more of an example for other stuff, as a logger would be a global. Not a singleton, but a global. (BTW, I have no clue why the physics world (or really, any of the worlds) would have a pointer/reference to the renderer)

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 5:11 pm
by CABAListic
nullsquared wrote: You can synchronise it that way using a simple global, too (for example, my link does synchronisation via std::clog). Like I said, it does not warrant a singleton.
You just don't get it, do you? The point is that there can only be one single instance of your global, because if you begin using more than one instance of your synchronisation object, then you can no longer correctly do the synchronisation.
In summary: You need a global to do the synchronisation, and you need exactly one instance. And that means it's a Singleton. As simple as that. If you use a global for the purpose, then it is still a Singleton, but your code does not enforce the single instance rule, i. e. you must ensure the single instance manually. The Singleton pattern prevents a possible programmer error, and therefore it's superiour to your global.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 5:14 pm
by nullsquared
CABAListic wrote:
nullsquared wrote: You can synchronise it that way using a simple global, too (for example, my link does synchronisation via std::clog). Like I said, it does not warrant a singleton.
You just don't get it, do you? The point is that there can only be one single instance of your global, because if you begin using more than one instance of your synchronisation object, then you can no longer correctly do the synchronisation.
What, are you going to "accidentally" make a second global? :roll:
In summary: You need a global to do the synchronisation, and you need exactly one instance. And that means it's a Singleton. As simple as that. If you use a global for the purpose, then it is still a Singleton, but your code does not enforce the single instance rule, i. e. you must ensure the single instance manually. The Singleton pattern prevents a possible programmer error, and therefore it's superiour to your global.
See this:
nullsquared wrote: Image
Wikipedia wrote: In software engineering, the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 5:24 pm
by JohnJ
Render system? gfx::renderer has nothing to do with Ogre::RenderSystem. It is what its name implies - a renderer. It abstracts away rendering (for example, I have both a forwardRenderer and a deferredRenderer - the main game can use one, but an in-game computer can use the other).
I knew that. Having both a forwardRenderer and deferredRenderer makes even less sense to me. How do you handle transparency? In my engine it's automatic because it's all managed by one Renderer (not a singleton btw).
And you're calling me the stubborn teenager.
I didn't call you a stubborn teenager, I said your post shows a common mistake made be teenagers, regardless of whether you're a teenager or not. Even if you are a teenager, it doesn't mean you can't at least try to act professionally. That's all I meant. BTW, I don't usually reveal this publicly, but I'm a teenager too. Though I'm certainly not as experienced as people here like sinbad, xavier, etc. (who's opinions btw I greatly respect simply because their experience give it more weight in my opinion), I've been employed professionally as a software engineer for a few years to say the least (currently as a lead 3D engine programmer in the games industry), long enough anyway to know that I don't know everything (there's always more to learn), and that a statement like "singletons are not to be used, period" would be foolish even if it seemed true based on my limited experience.
In summary: You need a global to do the synchronisation, and you need exactly one instance. And that means it's a Singleton. As simple as that.
He just doesn't get it.

nullsquared: As to wikipedia, scroll down a little:
wikipedia wrote:Implementation of a singleton pattern must satisfy the single instance and global access principles. It requires a mechanism to access the singleton class member without creating a class object and a mechanism to persist the value of class members among class objects.
A singleton is essentially a global variable reference to a class, with error checking to crash if more than one instance is created.

CABAListic is correct:
If you use a global for the purpose, then it is still a Singleton, but your code does not enforce the single instance rule

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 6:37 pm
by CABAListic
nullsquared wrote: What, are you going to "accidentally" make a second global? :roll:
There are many errors you are not likely to make. And still, you will protect your code against them if possible. The point is that the singleton pattern fits the issue 100% (which is to express a singleton) and, in this case, comes at no cost (since you've failed to name a single disadvantage). You don't need to use a singleton, but your arguments (so far) against using them just don't apply.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 7:04 pm
by nullsquared
CABAListic wrote:
nullsquared wrote: What, are you going to "accidentally" make a second global? :roll:
There are many errors you are not likely to make. And still, you will protect your code against them if possible. The point is that the singleton pattern fits the issue 100% (which is to express a singleton) and, in this case, comes at no cost (since you've failed to name a single disadvantage). You don't need to use a singleton, but your arguments (so far) against using them just don't apply.
That's only for a log manager. For a log manager, all data goes in, and no data comes out. That's why you can justify a log as a singleton. Though, I still do not see why you would need to make it a singleton instead of simply having a global logger.
JohnJ wrote:
Render system? gfx::renderer has nothing to do with Ogre::RenderSystem. It is what its name implies - a renderer. It abstracts away rendering (for example, I have both a forwardRenderer and a deferredRenderer - the main game can use one, but an in-game computer can use the other).
I knew that. Having both a forwardRenderer and deferredRenderer makes even less sense to me. How do you handle transparency? In my engine it's automatic because it's all managed by one Renderer (not a singleton btw).
Ugh here we go, off topic again. Not both as in at the same time. I can do this:

Code: Select all

if (userSelectedDeferred)
    _renderer.reset(new deferredRenderer(...));
else
    _renderer.reset(new forwardRenderer(...));
Transparency is handled like in any other deferred renderer, via a forward pass for transparent objects.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 7:07 pm
by Kojack
To quote the original Gang Of Four book "Design Patterns: Elements Of Reusable Object Oriented Software":
Singleton: Ensure a class only has one instance, and provide a global point of access to it.

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 7:13 pm
by CABAListic
nullsquared wrote: That's only for a log manager. For a log manager, all data goes in, and no data comes out. That's why you can justify a log as a singleton. Though, I still do not see why you would need to make it a singleton instead of simply having a global logger.
In summary (as stated before): Automatic self-creation, no explicit setup code necessary, safeguard against multiple instances. If you have no use for either of these, don't use it. I'm not trying to convince you to change your log system. If your system works fine, there's no need to change it. And the same is true for mine. I'd merely like you to take a less fanatical and more pragmatic stance at the issue :)

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 10:38 pm
by nikki
So, what nullsquared, do you particularly dislike: Global access, or Singletons (the only-one-instance idea)?

I like global access. :P

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 10:58 pm
by jacmoe
If I need a global, I very much prefer a singleton over a plain variable.
You can do a lot with dependency injection, but sometimes a singleton is a better option.
There are a lot of issues with singletons, as we've talked about in previous singleton topics, like hidden dependencies, etc. - but it's there.
Just like static class members are there.
And globals.
Things are easier in Java or C# (where there's no such thing as a non-class object).

Re: Singleton Discussion

Posted: Sun Jul 05, 2009 11:12 pm
by Klaim
That's only for a log manager. For a log manager, all data goes in, and no data comes out. That's why you can justify a log as a singleton. Though, I still do not see why you would need to make it a singleton instead of simply having a global logger.
Well the graphic rendering system interface of the computers my software runs on is unique and accessible as a environnement resources from the code point of view. So I need a Singleton class as interface to this system to reflect the uniqueness and the environemental - global - access. Currently I uses Ogre to do this. I don't allow all the modules of my project to access this singleton class, but the modules that are allowed to access it can use it from anywhere.

I don't see why it would be always a bad idea to use singleton types. As other already pointed, experience shows that each solution is a tool with drawbacks and advantages that you have to understand before mastering it. It's good to experiment extreme rules to understand the drawbacks too, but it's not a good thing to totally adhere to them. We see the points you're making here but they are valid only in a perfect world.