3

I came up with this while trying to create a singleton. Example: ( I am trying to make MySelf a singleton which is thread safe and without using double checked locking )

class MySelf
{
private:
    string Name;
    int Age;

    MySelf()
    {
        Name = "Deamonpog";
        Age = 24;
        cout << "Constructing MySelf : " << Name << endl;
    };

    friend class MySingleton;

public:
    ~MySelf(){ cout << "Destructing MySelf : " << Name << endl; };

    int MyAge() const
    {
        return Age;
    }
};

class MySingleton
{
private:
    static MySelf mself;
public:
    static MySelf * GetInstance()
    {
        return &mself;
    }
};

MySelf MySingleton::mself;

Now i can easily use it like,

cout << "I am " << MySingleton::GetInstance()->MyAge() << endl;

I dont want lazy initialization because the class i am gonna create is going to be there from the start to end. But is this thread safe? ( to my knowledge it seems ok )

If this is ok, then shall i use generic programming like this,

template <class T>
class GenericSingleton
{
private:
    static T _instance;

public:
    static T * GetInstance()
    {
        return &_instance;
    }
};

template <class T>
T GenericSingleton<T>::_instance;

So i can use this with any other class too. and i just have to add friend class GenericSingleton<MySelf>; to the needed sigleton ( e.g. to MySelf class ).

Could this implementation cause trouble? I am actually creating a library. Some singletons are to be exported and some are not. Also what if this is for not a library but just another application?

-- EDIT --

So now i have to do it like this (since i am using VC++ which still doesn't support C++11 ) ,

static MySelf & GetInstance()
{
    WaitForMutex(mymutex); // some function from the threading library
    if( NULL == _instance )
    {
         _instance = new MySelf();
    }
    ReleaseMutex(mymutex); // release function of the same library
    Return _instance;
}

And tell the user to use the function once and cache it for usage after that. ( Or i can also rename the function to Initialize() and make another method for just returning the reference without any lock or creation. ) So where does the mymutex should be? and where should it be initialized?

6
  • So , where i start. Why is your MySelf ctor private?! if this hasn't any real reason, i would set it to public. Then you can avoid friend ;) I would create a ctor for your class GenericSingleton how should be private, that nobody could make an instance of it. And yes, your GenericSingleton Class looks well. Commented Nov 29, 2012 at 9:43
  • @demonking : No. all i want is to make the MySelf class a singleton. Commented Nov 29, 2012 at 9:52
  • You may want a peek at this question concerning thread safety of Meyer's Singleton, while you're perusing the db. Commented Nov 29, 2012 at 9:53
  • but I am using C++03 :P and its VC++ Commented Nov 29, 2012 at 10:10
  • Note: singleton is considered an anti-pattern. Don’t use it. Commented Nov 29, 2012 at 13:52

2 Answers 2

6

No, but it's not the primary issue.

The initialization of global objects (such as static) is unordered across translation units; meaning that if during the creation of one global I was calling MySingleton::GetInstance() I could end up with a pointer to unitialized memory.

See Initialization Order Fiasco.

On top of that, if I were to have a second thread starting up during this phase of initialization, it could access to a partially initialized object.

In general, the recommendation is to use Meyer's Singleton:

MySelf& MySelf::Instance() { static MySelf S; return S; }

which sidesteps the initialization order fiasco in two ways:

  • it is guaranteed that the object be initialized when Instance() returns
  • from C++11 onwards, compilers are required to instrument the initialization code such that a re-entrant access during initialization is detected (gcc already did in C++03)

furthermore, from C++11 onwwards, this is required to be thread-safe: that is, shall another thread call Instance() while the object is being constructed it will wait patiently until the end of the construction and then return the same instance as all other threads (gcc already did in C++03).

Note: using an extraneous class is just more typing for no added value, ditch it.

Sign up to request clarification or add additional context in comments.

9 Comments

but i am using an old compiler and thats why i didn't use the mayers version and that is the reason for creating another class as a friend and giving it a static varible instance of MySelf. :P i guess every attempt has a disadvantage :P hehe...
Is 'Meyer's Singleton' guaranteed to be lock-free in c++11? If not then it's next to useless I'm afraid.
In c++11 the static inside function scope will also be initialized at the begining. rite? but if thats true, the initialization order fiasco will affect it rite?
@Deamonpog No, it won't. It will be initialized the first time the function is entered, so you're guaranteed that the object is constructed properly once the function returns, which is the first time you can use the object from outer code, anyway.
then, what can i do for thread safety issue of it ? ( im not using C++11 )
|
5

Here is simpler implementation:

template <class T>
class GenericSingleton
{
public:
    static T& GetInstance()
    {
        static T _instance;
        return _instance;
    }
};

It also thread safe in C++11, because static variable creates before any thread.

7 Comments

How does this answer his question?
What's the point of returning a pointer ? Is there any chance that it might be null ?
@KillianDS: the justification is wrong actually but the premise is right. It is thread-safe starting in C++11, it was already thread-safe when compiling with gcc in C++03 (and I think guaranteed by the Itanium ABI actually).
I didnt want to do this because i read in several places that static inside a function scope is NOT thread safe. isn't it?
@Deamonpog It’s not thread safe in C++03 simply because the C++03 standard doesn’t know about threads. In C++03, there is no pure C++ implementation which can be thread safe.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.