blob: dc200cf572bfec30f904e0754f89984aff1b18af [file] [log] [blame]
Howard Hinnant92827182011-05-24 22:01:16 +00001//===----------------------------- 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 "cxxabi.h"
11
12#include <cassert>
Eric Fiselierd872a692014-11-24 22:42:03 +000013
Asiri Rathnayakeb62a4dd2016-09-21 09:09:32 +000014#ifndef _LIBCXXABI_HAS_NO_THREADS
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000015#include <thread>
Eric Fiselierd872a692014-11-24 22:42:03 +000016#endif
Howard Hinnant92827182011-05-24 22:01:16 +000017
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000018// Ensure that we initialize each variable once and only once.
Howard Hinnant92827182011-05-24 22:01:16 +000019namespace test1 {
20 static int run_count = 0;
21 int increment() {
22 ++run_count;
23 return 0;
24 }
25 void helper() {
26 static int a = increment();
Eric Fiselier08bf03c2016-12-24 00:37:13 +000027 ((void)a);
Howard Hinnant92827182011-05-24 22:01:16 +000028 }
29 void test() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +000030 static int a = increment(); ((void)a);
Howard Hinnant92827182011-05-24 22:01:16 +000031 assert(run_count == 1);
Eric Fiselier08bf03c2016-12-24 00:37:13 +000032 static int b = increment(); ((void)b);
Howard Hinnant92827182011-05-24 22:01:16 +000033 assert(run_count == 2);
34 helper();
35 assert(run_count == 3);
36 helper();
37 assert(run_count == 3);
38 }
39}
40
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000041// When initialization fails, ensure that we try to initialize it again next
42// time.
Howard Hinnant92827182011-05-24 22:01:16 +000043namespace test2 {
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +000044#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
Howard Hinnant92827182011-05-24 22:01:16 +000045 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();
Eric Fiselier08bf03c2016-12-24 00:37:13 +000053 assert(false);
54 ((void)a);
Howard Hinnant92827182011-05-24 22:01:16 +000055 } catch (...) {}
56 }
57 void test() {
58 helper();
59 assert(run_count == 1);
60 helper();
61 assert(run_count == 2);
62 }
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +000063#else
64 void test() {}
65#endif
Howard Hinnant92827182011-05-24 22:01:16 +000066}
67
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000068// Check that we can initialize a second value while initializing a first.
69namespace test3 {
70 int zero() {
71 return 0;
72 }
73
74 int one() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +000075 static int b = zero(); ((void)b);
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000076 return 0;
77 }
78
79 void test() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +000080 static int a = one(); ((void)a);
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000081 }
82}
83
Asiri Rathnayakeb62a4dd2016-09-21 09:09:32 +000084#ifndef _LIBCXXABI_HAS_NO_THREADS
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000085// A simple thread test of two threads racing to initialize a variable. This
86// isn't guaranteed to catch any particular threading problems.
87namespace test4 {
88 static int run_count = 0;
89 int increment() {
90 ++run_count;
Howard Hinnant25f18072011-06-07 19:56:49 +000091 return 0;
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000092 }
93
94 void helper() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +000095 static int a = increment(); ((void)a);
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000096 }
97
98 void test() {
99 std::thread t1(helper), t2(helper);
100 t1.join();
101 t2.join();
Howard Hinnant25f18072011-06-07 19:56:49 +0000102 assert(run_count == 1);
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000103 }
104}
105
106// Check that we don't re-initialize a static variable even when it's
107// encountered from two different threads.
108namespace test5 {
109 static int run_count = 0;
110 int zero() {
111 ++run_count;
112 return 0;
113 }
114
115 int one() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +0000116 static int b = zero(); ((void)b);
Howard Hinnant25f18072011-06-07 19:56:49 +0000117 return 0;
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000118 }
119
120 void another_helper() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +0000121 static int a = one(); ((void)a);
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000122 }
123
124 void helper() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +0000125 static int a = one(); ((void)a);
Howard Hinnant25f18072011-06-07 19:56:49 +0000126 std::thread t(another_helper);
127 t.join();
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000128 }
129
130 void test() {
131 std::thread t(helper);
132 t.join();
Howard Hinnant25f18072011-06-07 19:56:49 +0000133 assert(run_count == 1);
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000134 }
135}
Asiri Rathnayakeb62a4dd2016-09-21 09:09:32 +0000136#endif /* _LIBCXXABI_HAS_NO_THREADS */
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000137
Howard Hinnant92827182011-05-24 22:01:16 +0000138int main()
139{
140 test1::test();
141 test2::test();
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000142 test3::test();
Asiri Rathnayakeb62a4dd2016-09-21 09:09:32 +0000143#ifndef _LIBCXXABI_HAS_NO_THREADS
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000144 test4::test();
145 test5::test();
Eric Fiselierd872a692014-11-24 22:42:03 +0000146#endif
Howard Hinnant92827182011-05-24 22:01:16 +0000147}