1 /* This program is used to test that one-time-construction 2 * works correctly, even in the presence of several threads. 3 */ 4 5 #include <new> 6 #include <pthread.h> 7 #include <stdio.h> 8 9 #define MAX_THREADS 100 10 11 class Foo { 12 public: 13 Foo() { mValue++; } 14 int getValue() { return mValue; } 15 private: 16 static int mValue; 17 }; 18 19 int Foo::mValue; 20 21 static Foo* getInstance(void) 22 { 23 // This construct forces the static creation of _instance 24 // the first time that getInstance() is called, in a thread-safe 25 // way. 26 static Foo _instance; 27 return &_instance; 28 } 29 30 static Foo* sInstances[MAX_THREADS]; 31 static pthread_t sThreads[MAX_THREADS]; 32 33 static void* thread_run(void* arg) 34 { 35 int index = reinterpret_cast<int>(arg); 36 sInstances[index] = getInstance(); 37 return NULL; 38 } 39 40 int main(void) 41 { 42 /* Create all the threads */ 43 for (int nn = 0; nn < MAX_THREADS; nn++) { 44 pthread_create( &sThreads[nn], NULL, thread_run, reinterpret_cast<void*>(nn) ); 45 } 46 /* Wait for their completion */ 47 for (int nn = 0; nn < MAX_THREADS; nn++) { 48 void* dummy; 49 pthread_join( sThreads[nn], &dummy ); 50 } 51 /* Get the instance */ 52 Foo* foo = getInstance(); 53 54 if (foo == NULL) { 55 fprintf(stderr, "ERROR: Foo instance is NULL!\n"); 56 return 1; 57 } 58 59 if (foo->getValue() != 1) { 60 fprintf(stderr, "ERROR: Foo constructor called %d times (1 expected)\n", 61 foo->getValue()); 62 return 2; 63 } 64 65 int count = 0; 66 for (int nn = 0; nn < MAX_THREADS; nn++) { 67 if (sInstances[nn] != foo) 68 count++; 69 } 70 71 if (count != 0) { 72 fprintf(stderr, "ERROR: There are %d invalid instance pointers!\n", count); 73 return 3; 74 } 75 return 0; 76 } 77