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