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