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