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. 20namespace 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. 43namespace test2 { 44 static int run_count = 0; 45 int increment() { 46 ++run_count; 47 throw 0; 48 } 49 void helper() { 50 try { 51 static int a = increment(); 52 assert(0); 53 } catch (...) {} 54 } 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. 64namespace test3 { 65 int zero() { 66 return 0; 67 } 68 69 int one() { 70 static int b = zero(); 71 return 0; 72 } 73 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. 82namespace test4 { 83 static int run_count = 0; 84 int increment() { 85 ++run_count; 86 return 0; 87 } 88 89 void helper() { 90 static int a = increment(); 91 } 92 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. 103namespace test5 { 104 static int run_count = 0; 105 int zero() { 106 ++run_count; 107 return 0; 108 } 109 110 int one() { 111 static int b = zero(); 112 return 0; 113 } 114 115 void another_helper() { 116 static int a = one(); 117 } 118 119 void helper() { 120 static int a = one(); 121 std::thread t(another_helper); 122 t.join(); 123 } 124 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 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