Singleton Quest?

Started by
5 comments, last by fyhuang 19 years, 2 months ago
Hello all, I have some question about using Signleton class would like to discuss with you guys. When we decide a singleton, sometimes we do this, Example 1:

class A 
{
 private :
   A();
 public :
   static A* GetInstance() 
   {
    static A a; 
    return &a
   }
}; 
This is absolutly good, but when compile in release mode, the compiler will sometimes make the GetInstance() inline, and it may causes the problem. So, another way to write a singleton class is, Example 2:

class A
{
 private :
   static A a;
   A();
 public:
   static A* GetInstance()
   {return &a};
};
It work fines even when the compiler change the GetInstance() to inline. But by doing that, we cannot control the order of when the singleton will be created, which is one of the main properties of a singelton class. Well, some of the solution I know for Exampl 1 is that we enforce the compiler not to change the GetInstance() to be inlined. Which I am not sure how can I do it in Visual .Net. Also, I don't know whether the command to do this is complier dependent. However, personally, I don't think it is a good solution since the function GetInstance() is so simple, and it should be inlined. By enforce the compiler to make it not inline may not be a very good approach. Another problem of using Singleton is that if the class require some parameters to pass into the constructor, what is the best solution for that? Also, if I want to do a subclass from a Singleton, what is the best way to do that too? Thanks! Edit: added tags. <!--EDIT--><span class=editedby><!--/EDIT-->[Edited by - hplus0603 on February 10, 2005 2:04:23 PM]<!--EDIT--></span><!--/EDIT-->
Nachi Lau (In Christ, I never die)www.sky-dio.com/Nachi
Advertisement
How about:

class A{    static A *singleton;    void createSingleton()    {        singleton = new A();    }    void getSingleton()    {        return singleton;    }};


This way you can control the order in which it's created, by calling createSingleton().

Cheers!

[edit] Or better yet, put the code in createSingleton() into the constructor, and you can then merely do:

new A();

To setup the singleton.
- fyhuang [ site ]
A common solution:
    class A    {    private:        static A * a;        A();    public:        static A* GetInstance()        {            if ( !a )            {                a = new A;            }            return a;        }    };    ...    A * A::a = 0; 

John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Quote:
        static A* GetInstance()        {            if ( !a )            {                a = new A;            }            return a;        }



That's pretty much what the compiler generates for the function static instance code, too; you just made it explicit. The problem with all of those approaches is that it's not thread-safe, so if two threads try to initialize the variable at the same time, you're screwed.

Usually, you don't create threads in your static constructors, though, so you can get around this by using the function-static instance, but then ALSO creating a static object whose only job it is to call the GetInstance() function to make sure the singleton is created when you hit main().

Note: the semantics of the function-level static are very clear in the standard. If writing the original code "causes problems" with inlining, then the compiler is broken, and you should upgrade. Neither latest GCC nor latest MSVC have a problem with that code, AFAICT.

Something like this should be sufficient for all uses:

template< class T > class Singleton {  public:    Singleton() { (*this)(); }    T * operator()() {      static T t;      return &t    }    static Singleton it;};Singleton< MyClass > gMyClassInstance;  // Two alternative uses, either is fine:  MyClass * single = gMyClassInstance();  MyClass * single = Singleton< MyClass >::it();

enum Bool { True, False, FileNotFound };
Hello,

Thanks for replay! However, the method that make a function called CreateSinglton() doesn't work since it requires the user to explicitly
create the singleton first, which may not always be possible, like, if
we have a static class that referencing the singleton class
in it constructor, then the progam will get a NULL pointer from GetInstance()eg,

class A
{
static A *singleton;
void createSingleton()
{
singleton = new A();
}
void getSingleton()
{
return singleton;
}

void f();
};

class B
{
static B b;

public :
B()
{a->getSingleton()->f();};
}


Thanks!





Nachi Lau (In Christ, I never die)www.sky-dio.com/Nachi
Quote:Original post by hplus0603

Note: the semantics of the function-level static are very clear in the standard. If writing the original code "causes problems" with inlining, then the compiler is broken, and you should upgrade. Neither latest GCC nor latest MSVC have a problem with that code, AFAICT.



Well, I am not sure about this, cause I get the problem on the lastest XBox compiler. I am not 100% sure whether the compiler in Visual Studio is the same one on XBox. I only know that they somehow related. Ha!

Thanks
Nachi Lau (In Christ, I never die)www.sky-dio.com/Nachi
Well, in my engine I create all singletons at engine startup (because, being singletons, they are probably large, hulking classes that only need be initialized once and deinitialized once). If you can't do that:

class A{    static A *singleton;    A()    {        assert( !singleton );        singleton = this;    }    static get()    {        if ( !singleton )        {            new A();        }        return singleton;    }};


This shouldn't have much of a performance impact (as compared to your first one) and should allow you control over when the singleton is made plus shouldn't be a problem for inlining. At least I think.

Hope it helps!

[edit] Ah, didn't see previous post. Sorry :).
- fyhuang [ site ]

This topic is closed to new replies.

Advertisement