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