126cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner/* This program is used to test that one-time-construction 226cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner * works correctly, even in the presence of several threads. 326cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner */ 426cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner 526cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner#include <new> 626cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner#include <pthread.h> 726cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner#include <stdio.h> 826cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner 926cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner#define MAX_THREADS 100 1026cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner 1126cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turnerclass Foo { 1226cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turnerpublic: 1326cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner Foo() { mValue++; } 1426cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner int getValue() { return mValue; } 1526cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turnerprivate: 1626cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner static int mValue; 1726cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner}; 1826cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner 1926cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turnerint Foo::mValue; 2026cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner 2126cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turnerstatic Foo* getInstance(void) 2226cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner{ 2326cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner // This construct forces the static creation of _instance 2426cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner // the first time that getInstance() is called, in a thread-safe 2526cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner // way. 2626cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner static Foo _instance; 2726cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner return &_instance; 2826cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner} 2926cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner 3026cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turnerstatic Foo* sInstances[MAX_THREADS]; 3126cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turnerstatic pthread_t sThreads[MAX_THREADS]; 3226cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner 3326cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turnerstatic void* thread_run(void* arg) 3426cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner{ 35638f6c2e430b6a10513b088a0e3a379950051c4aWenHan Gu int index = (int)(intptr_t)arg; 3626cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner sInstances[index] = getInstance(); 3726cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner return NULL; 3826cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner} 3926cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner 4026cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turnerint main(void) 4126cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner{ 4226cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner /* Create all the threads */ 4326cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner for (int nn = 0; nn < MAX_THREADS; nn++) { 4426cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner pthread_create( &sThreads[nn], NULL, thread_run, reinterpret_cast<void*>(nn) ); 4526cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner } 4626cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner /* Wait for their completion */ 4726cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner for (int nn = 0; nn < MAX_THREADS; nn++) { 4826cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner void* dummy; 4926cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner pthread_join( sThreads[nn], &dummy ); 5026cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner } 5126cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner /* Get the instance */ 5226cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner Foo* foo = getInstance(); 5326cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner 5426cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner if (foo == NULL) { 5526cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner fprintf(stderr, "ERROR: Foo instance is NULL!\n"); 5626cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner return 1; 5726cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner } 5826cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner 5926cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner if (foo->getValue() != 1) { 6026cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner fprintf(stderr, "ERROR: Foo constructor called %d times (1 expected)\n", 6126cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner foo->getValue()); 6226cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner return 2; 6326cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner } 6426cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner 6526cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner int count = 0; 6626cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner for (int nn = 0; nn < MAX_THREADS; nn++) { 6726cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner if (sInstances[nn] != foo) 6826cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner count++; 6926cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner } 7026cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner 7126cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner if (count != 0) { 7226cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner fprintf(stderr, "ERROR: There are %d invalid instance pointers!\n", count); 7326cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner return 3; 7426cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner } 7526cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner return 0; 7626cc9e3109d9df4dd7726edcb02982c26c207d20David 'Digit' Turner} 77