blob: a8b4be16e631c238ec1c81465b88f283f5d3fbba [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===----------------------------------------------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
Jonathan Roelofs8d86b2e2014-09-05 19:45:05 +00009//
10// UNSUPPORTED: libcpp-has-no-threads
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000011
12// <thread>
13
14// class thread
15
16// template <class F, class ...Args> thread(F&& f, Args&&... args);
17
Eric Fiselier07a4bec2015-03-10 20:46:04 +000018// UNSUPPORTED: sanitizer-new-delete
Eric Fiselier69697c82014-11-04 17:03:47 +000019
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000020#include <thread>
21#include <new>
22#include <cstdlib>
23#include <cassert>
24
Dan Albert1d4a1ed2016-05-25 22:36:09 -070025unsigned throw_one = 0xFFFF;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000026
27void* operator new(std::size_t s) throw(std::bad_alloc)
28{
29 if (throw_one == 0)
30 throw std::bad_alloc();
31 --throw_one;
32 return std::malloc(s);
33}
34
35void operator delete(void* p) throw()
36{
37 std::free(p);
38}
39
40bool f_run = false;
41
42void f()
43{
44 f_run = true;
45}
46
47class G
48{
49 int alive_;
50public:
51 static int n_alive;
52 static bool op_run;
53
54 G() : alive_(1) {++n_alive;}
55 G(const G& g) : alive_(g.alive_) {++n_alive;}
56 ~G() {alive_ = 0; --n_alive;}
57
58 void operator()()
59 {
60 assert(alive_ == 1);
61 assert(n_alive >= 1);
62 op_run = true;
63 }
64
65 void operator()(int i, double j)
66 {
67 assert(alive_ == 1);
68 assert(n_alive >= 1);
69 assert(i == 5);
70 assert(j == 5.5);
71 op_run = true;
72 }
73};
74
75int G::n_alive = 0;
76bool G::op_run = false;
77
Dan Albert1d4a1ed2016-05-25 22:36:09 -070078#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnant656bdc32011-05-16 18:40:35 +000079
80class MoveOnly
81{
82 MoveOnly(const MoveOnly&);
83public:
84 MoveOnly() {}
85 MoveOnly(MoveOnly&&) {}
86
87 void operator()(MoveOnly&&)
88 {
89 }
90};
91
92#endif
93
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000094int main()
95{
96 {
97 std::thread t(f);
98 t.join();
99 assert(f_run == true);
100 }
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700101 f_run = false;
102 {
103 try
104 {
105 throw_one = 0;
106 std::thread t(f);
107 assert(false);
108 }
109 catch (...)
110 {
111 throw_one = 0xFFFF;
112 assert(!f_run);
113 }
114 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000115 {
116 assert(G::n_alive == 0);
117 assert(!G::op_run);
118 std::thread t((G()));
119 t.join();
120 assert(G::n_alive == 0);
121 assert(G::op_run);
122 }
123 G::op_run = false;
124 {
125 try
126 {
127 throw_one = 0;
128 assert(G::n_alive == 0);
129 assert(!G::op_run);
130 std::thread t((G()));
131 assert(false);
132 }
133 catch (...)
134 {
135 throw_one = 0xFFFF;
136 assert(G::n_alive == 0);
137 assert(!G::op_run);
138 }
139 }
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700140#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000141 {
142 assert(G::n_alive == 0);
143 assert(!G::op_run);
144 std::thread t(G(), 5, 5.5);
145 t.join();
146 assert(G::n_alive == 0);
147 assert(G::op_run);
148 }
Howard Hinnant656bdc32011-05-16 18:40:35 +0000149 {
150 std::thread t = std::thread(MoveOnly(), MoveOnly());
151 t.join();
152 }
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700153#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000154}