Question

I was reading a paper on "Perils of double check locking by Scott Meyers". http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf

The author gives reasons why the double check lock fails (page 3, section 4). I was thinking of ways to get around this problem without using C++11. Not that I don't want to use C++ 11 but just to see if it is possible to solve it without using functions such as std::call_once, etc

class Singleton {
public:
    static Singleton* instance();

private:
    static Singleton* pInstance;
    int someData_;
};


Singleton* Singleton::instance() 
{
    class SeqAssign{
    public:
        SeqAssign(Singleton*& pInst, Singleton* pNew):
        pInstance(pInst), pNewedInst(pNew){
        }
        ~SeqAssign(){
            pInstance = pNewedInst;
        }

    private:
        Singleton*& pInstance;
        Singleton*  pNewedInst;
    };

    if (pInstance == 0) { // 1st test
        Lock lock;
        if (pInstance == 0) { // 2nd test
            SeqAssign seq(pInstance, new Singleton);
        }
    }
    return pInstance;
}

Will the code in Singleton::instance() work in a multi-threaded environment as the order in which the constructor and destructor is called for the SeqAssign class is deterministic.

Was it helpful?

Solution

No. The variable pInstance is accessed from more than one thread. It is modified. The code has undefined behavior. And I'm not sure what you thing SeqAssign will do, since it doesn't introduce any additional inter-thread sequencing.

There is no way to make double checked logging work in standard C++; all of the solutions involve atomic variables (possibly implemented using inline assembler) or thread local storage.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top