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:
Foo()13 Foo() { mValue++; }
getValue()14 int getValue() { return mValue; }
15 private:
16 static int mValue;
17 };
18
19 int Foo::mValue;
20
getInstance(void)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
thread_run(void * arg)33 static void* thread_run(void* arg)
34 {
35 int index = (int)(intptr_t)arg;
36 sInstances[index] = getInstance();
37 return NULL;
38 }
39
main(void)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