blob: ef8671701579519737988ea3a9e59927565454cf [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
Eric Fiselierd872a692014-11-24 22:42:03 +000010#include "../src/config.h"
Howard Hinnant92827182011-05-24 22:01:16 +000011#include "cxxabi.h"
12
13#include <cassert>
Eric Fiselierd872a692014-11-24 22:42:03 +000014
Asiri Rathnayakeb62a4dd2016-09-21 09:09:32 +000015#ifndef _LIBCXXABI_HAS_NO_THREADS
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000016#include <thread>
Eric Fiselierd872a692014-11-24 22:42:03 +000017#endif
Howard Hinnant92827182011-05-24 22:01:16 +000018
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000019// Ensure that we initialize each variable once and only once.
Howard Hinnant92827182011-05-24 22:01:16 +000020namespace 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();
Eric Fiselier08bf03c2016-12-24 00:37:13 +000028 ((void)a);
Howard Hinnant92827182011-05-24 22:01:16 +000029 }
30 void test() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +000031 static int a = increment(); ((void)a);
Howard Hinnant92827182011-05-24 22:01:16 +000032 assert(run_count == 1);
Eric Fiselier08bf03c2016-12-24 00:37:13 +000033 static int b = increment(); ((void)b);
Howard Hinnant92827182011-05-24 22:01:16 +000034 assert(run_count == 2);
35 helper();
36 assert(run_count == 3);
37 helper();
38 assert(run_count == 3);
39 }
40}
41
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000042// When initialization fails, ensure that we try to initialize it again next
43// time.
Howard Hinnant92827182011-05-24 22:01:16 +000044namespace test2 {
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +000045#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
Howard Hinnant92827182011-05-24 22:01:16 +000046 static int run_count = 0;
47 int increment() {
48 ++run_count;
49 throw 0;
50 }
51 void helper() {
52 try {
53 static int a = increment();
Eric Fiselier08bf03c2016-12-24 00:37:13 +000054 assert(false);
55 ((void)a);
Howard Hinnant92827182011-05-24 22:01:16 +000056 } catch (...) {}
57 }
58 void test() {
59 helper();
60 assert(run_count == 1);
61 helper();
62 assert(run_count == 2);
63 }
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +000064#else
65 void test() {}
66#endif
Howard Hinnant92827182011-05-24 22:01:16 +000067}
68
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000069// Check that we can initialize a second value while initializing a first.
70namespace test3 {
71 int zero() {
72 return 0;
73 }
74
75 int one() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +000076 static int b = zero(); ((void)b);
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000077 return 0;
78 }
79
80 void test() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +000081 static int a = one(); ((void)a);
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000082 }
83}
84
Asiri Rathnayakeb62a4dd2016-09-21 09:09:32 +000085#ifndef _LIBCXXABI_HAS_NO_THREADS
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000086// A simple thread test of two threads racing to initialize a variable. This
87// isn't guaranteed to catch any particular threading problems.
88namespace test4 {
89 static int run_count = 0;
90 int increment() {
91 ++run_count;
Howard Hinnant25f18072011-06-07 19:56:49 +000092 return 0;
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000093 }
94
95 void helper() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +000096 static int a = increment(); ((void)a);
Nick Lewycky5dfef8d2011-06-04 18:01:24 +000097 }
98
99 void test() {
100 std::thread t1(helper), t2(helper);
101 t1.join();
102 t2.join();
Howard Hinnant25f18072011-06-07 19:56:49 +0000103 assert(run_count == 1);
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000104 }
105}
106
107// Check that we don't re-initialize a static variable even when it's
108// encountered from two different threads.
109namespace test5 {
110 static int run_count = 0;
111 int zero() {
112 ++run_count;
113 return 0;
114 }
115
116 int one() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +0000117 static int b = zero(); ((void)b);
Howard Hinnant25f18072011-06-07 19:56:49 +0000118 return 0;
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000119 }
120
121 void another_helper() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +0000122 static int a = one(); ((void)a);
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000123 }
124
125 void helper() {
Eric Fiselier08bf03c2016-12-24 00:37:13 +0000126 static int a = one(); ((void)a);
Howard Hinnant25f18072011-06-07 19:56:49 +0000127 std::thread t(another_helper);
128 t.join();
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000129 }
130
131 void test() {
132 std::thread t(helper);
133 t.join();
Howard Hinnant25f18072011-06-07 19:56:49 +0000134 assert(run_count == 1);
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000135 }
136}
Asiri Rathnayakeb62a4dd2016-09-21 09:09:32 +0000137#endif /* _LIBCXXABI_HAS_NO_THREADS */
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000138
Howard Hinnant92827182011-05-24 22:01:16 +0000139int main()
140{
141 test1::test();
142 test2::test();
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000143 test3::test();
Asiri Rathnayakeb62a4dd2016-09-21 09:09:32 +0000144#ifndef _LIBCXXABI_HAS_NO_THREADS
Nick Lewycky5dfef8d2011-06-04 18:01:24 +0000145 test4::test();
146 test5::test();
Eric Fiselierd872a692014-11-24 22:42:03 +0000147#endif
Howard Hinnant92827182011-05-24 22:01:16 +0000148}