• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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