views:

103

answers:

3

Hi guys, this is my first question on stack overflow, so be gentle.

Let me first explain the exact behavior I would like to see. If you are familiar with C# then you know that declaring a variable as "readonly" allows a programmer to assign some value to that variable exactly once. Further attempts to modify the variable will result in an error.

What I am after: I want to make sure that any and all single-ton classes I define can be predictably instantiated exactly once in my program (more details at the bottom).

My approach to realizing my goal is to use extern to declare a global reference to the single-ton (which I will later instantiate at a time I choose. What I have sort of looks like this,

namespace Global
{
    extern Singleton& mainInstance; // not defined yet, but it will be later!
}

int main()
{
    // now that the program has started, go ahead and create the singleton object
    Singleton& Global::mainInstance = Singleton::GetInstance(); // invalid use of qualified name
    Global::mainInstance = Singleton::GetInstance(); // doesn't work either :( 
}

class Singleton
{
    /* Some details ommited */

    public:
        Singleton& GetInstance()
        {
            static Singleton instance; // exists once for the whole program
            return instance;
        }
}

However this does not really work, and I don't know where to go from here.

Some details about what I'm up against:

I'm concerned about threading as I am working on code that will deal with game logic while communicating with several third-party processes and other processes I will create. Eventually I would have to implement some kind of synchronization so multiple threads could access the information in the Singleton class without worry. Because I don't know what kinds of optimizations I might like to do, or exactly what threading entails (never done a real project using it), I was thinking that being able to predictably control when Singletons were instantiated would be a Good Thing.

Imagine if Process A creates Process B, where B contains several Singletons distributed against multiple files and/or libraries. It could be a real nightmare if I can not reliably ensure the order these singleton objects are instantiated (because they could depend on each other, and calling methods on a NULL object is generally a Bad Thing).

If I were in C# I would just use the readonly keyword, but is there any way I can implement this (compiler supported) behavior in C++? Is this even a good idea? Thanks for any feedback.


Edit

If I was locked in to following the code example above, the selected answer would be the easiest way to do what I needed. I decided to change the pattern away from singleton though, even though I only plan to ever make one of these EntryPoint objects.

class EntryPoint
{

    /* Intentionally defined this way to discourage creation */
    EntryPoint(const EntryPoint &); // undefined & private
    EntryPoint& operator=(const EntryPoint &); // undefined & private

    // public
    EntryPoint()
    {
        /* All of the action is performed here! */
    }

    /* Other supporting functions */
}

// The easier to understand main function!
int main()
{
    EntryPoint * ep = new EntryPoint(); // transfer control to the entrypoint
    delete ep;
}

One of the reasons I was thinking I would need all these singletons is I plan to create a larger architecture that would support modular plugin-type applications. I also wanted more error-checking and memory protection to minimize memory leaks. I was happy to find that the cross-platform Qt (http://qt.nokia.com/) offers a guarded pointer and other cool features.

+1  A: 

Why not just use Singleton::GetInstance directly? Why do you need to store it in a (readonly) global? This solves dependency issues as well.

strager
+1 This is how I would call the Singleton GetInstance method too.
David Relihan
Half of me wants to know if it possible. But what I am trying to do is separate instantiation from access. My feeling is that someday I may create an AccessManager class that would be responsible for speeding up the access to global data (which may require querying a database, who knows) using caching techniques or something more complicated. Right now its not so bad because its simple, but I don't want to be in a situation where it becomes difficult to optimize because I have many calls to Singleton::GetInstance() all throughout the codebase.
Tommy Fisk
Can you create a class (or several classes) with static methods such as `GetGraphicsEngine` and `GetInputEngine` which, for now, call `Singleton::GetInstance`?
strager
@Tommy: a better solution is to *not make it a singleton in the first place*
jalf
@jalf, Agreed. [character limit]
strager
+1  A: 

Only allow access by calling:

Singleton::GetInstance 

Enforce this by making your copy and assignment constructors private

private:
   Singleton(){}
   Singleton(Singleton const&){}; //copy ctor private
   Singleton& operator=(Singleton const&){}; 
David Relihan
and Singleton::GetInstance is static
Joshua
A: 

Imagine if Process A creates Process B, where B contains several Singletons

What exactly do you think you need all these Singletons for? Are you aware of the Anti Singleton Movement? ;-)

FredOverflow
Amusing video :)
Matthieu M.
@Matt: By "amusing", do you mean "interesting" or "ludicrous"?
FredOverflow
A bit of both I guess :) I only viewed the first 10 minutes, and while I agree that global state should be avoided (don't we know it all ?), I also know from experience that it exists: it's called the outside world (databases, other applications, ...). I am glad for the link nonetheless. And congratulation on achieving 4k :)
Matthieu M.