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