1*5a83710eSEric Fiselier //===----------------------------------------------------------------------===//
2*5a83710eSEric Fiselier //
3*5a83710eSEric Fiselier //                     The LLVM Compiler Infrastructure
4*5a83710eSEric Fiselier //
5*5a83710eSEric Fiselier // This file is dual licensed under the MIT and the University of Illinois Open
6*5a83710eSEric Fiselier // Source Licenses. See LICENSE.TXT for details.
7*5a83710eSEric Fiselier //
8*5a83710eSEric Fiselier //===----------------------------------------------------------------------===//
9*5a83710eSEric Fiselier //
10*5a83710eSEric Fiselier // UNSUPPORTED: libcpp-has-no-threads
11*5a83710eSEric Fiselier 
12*5a83710eSEric Fiselier // <thread>
13*5a83710eSEric Fiselier 
14*5a83710eSEric Fiselier // class thread
15*5a83710eSEric Fiselier 
16*5a83710eSEric Fiselier // template <class F, class ...Args> thread(F&& f, Args&&... args);
17*5a83710eSEric Fiselier 
18*5a83710eSEric Fiselier // UNSUPPORTED: asan, msan
19*5a83710eSEric Fiselier 
20*5a83710eSEric Fiselier #include <thread>
21*5a83710eSEric Fiselier #include <new>
22*5a83710eSEric Fiselier #include <cstdlib>
23*5a83710eSEric Fiselier #include <cassert>
24*5a83710eSEric Fiselier 
25*5a83710eSEric Fiselier unsigned throw_one = 0xFFFF;
26*5a83710eSEric Fiselier 
27*5a83710eSEric Fiselier void* operator new(std::size_t s) throw(std::bad_alloc)
28*5a83710eSEric Fiselier {
29*5a83710eSEric Fiselier     if (throw_one == 0)
30*5a83710eSEric Fiselier         throw std::bad_alloc();
31*5a83710eSEric Fiselier     --throw_one;
32*5a83710eSEric Fiselier     return std::malloc(s);
33*5a83710eSEric Fiselier }
34*5a83710eSEric Fiselier 
35*5a83710eSEric Fiselier void  operator delete(void* p) throw()
36*5a83710eSEric Fiselier {
37*5a83710eSEric Fiselier     std::free(p);
38*5a83710eSEric Fiselier }
39*5a83710eSEric Fiselier 
40*5a83710eSEric Fiselier bool f_run = false;
41*5a83710eSEric Fiselier 
42*5a83710eSEric Fiselier void f()
43*5a83710eSEric Fiselier {
44*5a83710eSEric Fiselier     f_run = true;
45*5a83710eSEric Fiselier }
46*5a83710eSEric Fiselier 
47*5a83710eSEric Fiselier class G
48*5a83710eSEric Fiselier {
49*5a83710eSEric Fiselier     int alive_;
50*5a83710eSEric Fiselier public:
51*5a83710eSEric Fiselier     static int n_alive;
52*5a83710eSEric Fiselier     static bool op_run;
53*5a83710eSEric Fiselier 
54*5a83710eSEric Fiselier     G() : alive_(1) {++n_alive;}
55*5a83710eSEric Fiselier     G(const G& g) : alive_(g.alive_) {++n_alive;}
56*5a83710eSEric Fiselier     ~G() {alive_ = 0; --n_alive;}
57*5a83710eSEric Fiselier 
58*5a83710eSEric Fiselier     void operator()()
59*5a83710eSEric Fiselier     {
60*5a83710eSEric Fiselier         assert(alive_ == 1);
61*5a83710eSEric Fiselier         assert(n_alive >= 1);
62*5a83710eSEric Fiselier         op_run = true;
63*5a83710eSEric Fiselier     }
64*5a83710eSEric Fiselier 
65*5a83710eSEric Fiselier     void operator()(int i, double j)
66*5a83710eSEric Fiselier     {
67*5a83710eSEric Fiselier         assert(alive_ == 1);
68*5a83710eSEric Fiselier         assert(n_alive >= 1);
69*5a83710eSEric Fiselier         assert(i == 5);
70*5a83710eSEric Fiselier         assert(j == 5.5);
71*5a83710eSEric Fiselier         op_run = true;
72*5a83710eSEric Fiselier     }
73*5a83710eSEric Fiselier };
74*5a83710eSEric Fiselier 
75*5a83710eSEric Fiselier int G::n_alive = 0;
76*5a83710eSEric Fiselier bool G::op_run = false;
77*5a83710eSEric Fiselier 
78*5a83710eSEric Fiselier #ifndef _LIBCPP_HAS_NO_VARIADICS
79*5a83710eSEric Fiselier 
80*5a83710eSEric Fiselier class MoveOnly
81*5a83710eSEric Fiselier {
82*5a83710eSEric Fiselier     MoveOnly(const MoveOnly&);
83*5a83710eSEric Fiselier public:
84*5a83710eSEric Fiselier     MoveOnly() {}
85*5a83710eSEric Fiselier     MoveOnly(MoveOnly&&) {}
86*5a83710eSEric Fiselier 
87*5a83710eSEric Fiselier     void operator()(MoveOnly&&)
88*5a83710eSEric Fiselier     {
89*5a83710eSEric Fiselier     }
90*5a83710eSEric Fiselier };
91*5a83710eSEric Fiselier 
92*5a83710eSEric Fiselier #endif
93*5a83710eSEric Fiselier 
94*5a83710eSEric Fiselier int main()
95*5a83710eSEric Fiselier {
96*5a83710eSEric Fiselier     {
97*5a83710eSEric Fiselier         std::thread t(f);
98*5a83710eSEric Fiselier         t.join();
99*5a83710eSEric Fiselier         assert(f_run == true);
100*5a83710eSEric Fiselier     }
101*5a83710eSEric Fiselier     f_run = false;
102*5a83710eSEric Fiselier     {
103*5a83710eSEric Fiselier         try
104*5a83710eSEric Fiselier         {
105*5a83710eSEric Fiselier             throw_one = 0;
106*5a83710eSEric Fiselier             std::thread t(f);
107*5a83710eSEric Fiselier             assert(false);
108*5a83710eSEric Fiselier         }
109*5a83710eSEric Fiselier         catch (...)
110*5a83710eSEric Fiselier         {
111*5a83710eSEric Fiselier             throw_one = 0xFFFF;
112*5a83710eSEric Fiselier             assert(!f_run);
113*5a83710eSEric Fiselier         }
114*5a83710eSEric Fiselier     }
115*5a83710eSEric Fiselier     {
116*5a83710eSEric Fiselier         assert(G::n_alive == 0);
117*5a83710eSEric Fiselier         assert(!G::op_run);
118*5a83710eSEric Fiselier         std::thread t((G()));
119*5a83710eSEric Fiselier         t.join();
120*5a83710eSEric Fiselier         assert(G::n_alive == 0);
121*5a83710eSEric Fiselier         assert(G::op_run);
122*5a83710eSEric Fiselier     }
123*5a83710eSEric Fiselier     G::op_run = false;
124*5a83710eSEric Fiselier     {
125*5a83710eSEric Fiselier         try
126*5a83710eSEric Fiselier         {
127*5a83710eSEric Fiselier             throw_one = 0;
128*5a83710eSEric Fiselier             assert(G::n_alive == 0);
129*5a83710eSEric Fiselier             assert(!G::op_run);
130*5a83710eSEric Fiselier             std::thread t((G()));
131*5a83710eSEric Fiselier             assert(false);
132*5a83710eSEric Fiselier         }
133*5a83710eSEric Fiselier         catch (...)
134*5a83710eSEric Fiselier         {
135*5a83710eSEric Fiselier             throw_one = 0xFFFF;
136*5a83710eSEric Fiselier             assert(G::n_alive == 0);
137*5a83710eSEric Fiselier             assert(!G::op_run);
138*5a83710eSEric Fiselier         }
139*5a83710eSEric Fiselier     }
140*5a83710eSEric Fiselier #ifndef _LIBCPP_HAS_NO_VARIADICS
141*5a83710eSEric Fiselier     {
142*5a83710eSEric Fiselier         assert(G::n_alive == 0);
143*5a83710eSEric Fiselier         assert(!G::op_run);
144*5a83710eSEric Fiselier         std::thread t(G(), 5, 5.5);
145*5a83710eSEric Fiselier         t.join();
146*5a83710eSEric Fiselier         assert(G::n_alive == 0);
147*5a83710eSEric Fiselier         assert(G::op_run);
148*5a83710eSEric Fiselier     }
149*5a83710eSEric Fiselier     {
150*5a83710eSEric Fiselier         std::thread t = std::thread(MoveOnly(), MoveOnly());
151*5a83710eSEric Fiselier         t.join();
152*5a83710eSEric Fiselier     }
153*5a83710eSEric Fiselier #endif  // _LIBCPP_HAS_NO_VARIADICS
154*5a83710eSEric Fiselier }
155