C++ and the Perils of Double-Checked Locking: Part 1
by Scott Meyers and Andrei Alexandrescu

Example 1:

1 // from the header file
2 class Singleton {
3 public:
4 static Singleton* instance();
5    ...
6 private:
7    static Singleton* pInstance;
8 };

9
10 // from the implementation file
11 Singleton* Singleton::pInstance = 0;
12
13 Singleton* Singleton::instance() {
14    if (pInstance == 0) {
15       pInstance = new Singleton;
16    }
17    return pInstance;
18 }



Example 2

Singleton* Singleton::instance() {
   Lock lock; // acquire lock (params omitted for simplicity)
   if (pInstance == 0) {
     pInstance = new Singleton;
   }
   return pInstance;
} // release lock (via Lock destructor)

Example 3:

Singleton* Singleton::instance() {
   if (pInstance == 0) { // 1st test
      Lock lock;
      if (pInstance == 0) { // 2nd test
         pInstance = new Singleton;
      }
   }
   return pInstance;
}

Example 4:

Singleton* Singleton::instance() {
   if (pInstance == 0) {
      Lock lock;
      if (pInstance == 0) {
         pInstance = // Step 3
            operator new(sizeof(Singleton)); // Step 1
         new (pInstance) Singleton; // Step 2
      }
   }
   return pInstance;
}


Example 5:

void Foo() {
   int x = 0, y = 0; // Statement 1
   x = 5; // Statement 2
   y = 10; // Statement 3
   printf("%d,_%d", x, y); // Statement 4
}


Example 6

Singleton* Singleton::instance() {
   if (pInstance == 0) {
      Lock lock;
      if (pInstance == 0) {
         Singleton* temp = new Singleton; // initialize to temp
         pInstance = temp; // assign temp to pInstance
      }
   }
   return pInstance;
}







1


