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