1 //===----------------------------------------------------------------------===//
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 // UNSUPPORTED: libcpp-has-no-threads
11 
12 // <thread>
13 
14 // class thread
15 
16 // template <class F, class ...Args> thread(F&& f, Args&&... args);
17 
18 // UNSUPPORTED: asan, msan
19 
20 #include <thread>
21 #include <new>
22 #include <cstdlib>
23 #include <cassert>
24 
25 unsigned throw_one = 0xFFFF;
26 
operator new(std::size_t s)27 void* 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 
operator delete(void * p)35 void  operator delete(void* p) throw()
36 {
37     std::free(p);
38 }
39 
40 bool f_run = false;
41 
f()42 void f()
43 {
44     f_run = true;
45 }
46 
47 class G
48 {
49     int alive_;
50 public:
51     static int n_alive;
52     static bool op_run;
53 
G()54     G() : alive_(1) {++n_alive;}
G(const G & g)55     G(const G& g) : alive_(g.alive_) {++n_alive;}
~G()56     ~G() {alive_ = 0; --n_alive;}
57 
operator ()()58     void operator()()
59     {
60         assert(alive_ == 1);
61         assert(n_alive >= 1);
62         op_run = true;
63     }
64 
operator ()(int i,double j)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 
75 int G::n_alive = 0;
76 bool G::op_run = false;
77 
78 #ifndef _LIBCPP_HAS_NO_VARIADICS
79 
80 class MoveOnly
81 {
82     MoveOnly(const MoveOnly&);
83 public:
MoveOnly()84     MoveOnly() {}
MoveOnly(MoveOnly &&)85     MoveOnly(MoveOnly&&) {}
86 
operator ()(MoveOnly &&)87     void operator()(MoveOnly&&)
88     {
89     }
90 };
91 
92 #endif
93 
main()94 int main()
95 {
96     {
97         std::thread t(f);
98         t.join();
99         assert(f_run == true);
100     }
101     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     }
115     {
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     }
140 #ifndef _LIBCPP_HAS_NO_VARIADICS
141     {
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     }
149     {
150         std::thread t = std::thread(MoveOnly(), MoveOnly());
151         t.join();
152     }
153 #endif  // _LIBCPP_HAS_NO_VARIADICS
154 }
155