• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===----------------------------- test_guard.cpp -------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "../src/config.h"
11 #include "cxxabi.h"
12 
13 #include <cassert>
14 #if !LIBCXXABI_SINGLE_THREADED
15 #  include <thread>
16 #endif
17 
18 // Ensure that we initialize each variable once and only once.
19 namespace test1 {
20     static int run_count = 0;
increment()21     int increment() {
22         ++run_count;
23         return 0;
24     }
helper()25     void helper() {
26         static int a = increment();
27     }
test()28     void test() {
29         static int a = increment();
30         assert(run_count == 1);
31         static int b = increment();
32         assert(run_count == 2);
33         helper();
34         assert(run_count == 3);
35         helper();
36         assert(run_count == 3);
37     }
38 }
39 
40 // When initialization fails, ensure that we try to initialize it again next
41 // time.
42 namespace test2 {
43     static int run_count = 0;
increment()44     int increment() {
45         ++run_count;
46         throw 0;
47     }
helper()48     void helper() {
49         try {
50             static int a = increment();
51             assert(0);
52         } catch (...) {}
53     }
test()54     void test() {
55         helper();
56         assert(run_count == 1);
57         helper();
58         assert(run_count == 2);
59     }
60 }
61 
62 // Check that we can initialize a second value while initializing a first.
63 namespace test3 {
zero()64     int zero() {
65         return 0;
66     }
67 
one()68     int one() {
69         static int b = zero();
70         return 0;
71     }
72 
test()73     void test() {
74         static int a = one();
75     }
76 }
77 
78 #if !LIBCXXABI_SINGLE_THREADED
79 // A simple thread test of two threads racing to initialize a variable. This
80 // isn't guaranteed to catch any particular threading problems.
81 namespace test4 {
82     static int run_count = 0;
increment()83     int increment() {
84         ++run_count;
85         return 0;
86     }
87 
helper()88     void helper() {
89         static int a = increment();
90     }
91 
test()92     void test() {
93         std::thread t1(helper), t2(helper);
94         t1.join();
95         t2.join();
96         assert(run_count == 1);
97     }
98 }
99 
100 // Check that we don't re-initialize a static variable even when it's
101 // encountered from two different threads.
102 namespace test5 {
103     static int run_count = 0;
zero()104     int zero() {
105         ++run_count;
106         return 0;
107     }
108 
one()109     int one() {
110         static int b = zero();
111         return 0;
112     }
113 
another_helper()114     void another_helper() {
115         static int a = one();
116     }
117 
helper()118     void helper() {
119         static int a = one();
120         std::thread t(another_helper);
121         t.join();
122     }
123 
test()124     void test() {
125         std::thread t(helper);
126         t.join();
127         assert(run_count == 1);
128     }
129 }
130 #endif
131 
main()132 int main()
133 {
134     test1::test();
135     test2::test();
136     test3::test();
137 #if !LIBCXXABI_SINGLE_THREADED
138     test4::test();
139     test5::test();
140 #endif
141 }
142