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 11class Foo { 12public: 13 Foo() { mValue++; } 14 int getValue() { return mValue; } 15private: 16 static int mValue; 17}; 18 19int Foo::mValue; 20 21static 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 30static Foo* sInstances[MAX_THREADS]; 31static pthread_t sThreads[MAX_THREADS]; 32 33static void* thread_run(void* arg) 34{ 35 int index = (int)(intptr_t)arg; 36 sInstances[index] = getInstance(); 37 return NULL; 38} 39 40int 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