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: sanitizer-new-delete
19 
20 #include <thread>
21 #include <new>
22 #include <cstdlib>
23 #include <cassert>
24 
25 #include "test_macros.h"
26 
27 unsigned throw_one = 0xFFFF;
28 
operator new(std::size_t s)29 void* operator new(std::size_t s) throw(std::bad_alloc)
30 {
31     if (throw_one == 0)
32         throw std::bad_alloc();
33     --throw_one;
34     return std::malloc(s);
35 }
36 
operator delete(void * p)37 void  operator delete(void* p) throw()
38 {
39     std::free(p);
40 }
41 
42 bool f_run = false;
43 
f()44 void f()
45 {
46     f_run = true;
47 }
48 
49 class G
50 {
51     int alive_;
52 public:
53     static int n_alive;
54     static bool op_run;
55 
G()56     G() : alive_(1) {++n_alive;}
G(const G & g)57     G(const G& g) : alive_(g.alive_) {++n_alive;}
~G()58     ~G() {alive_ = 0; --n_alive;}
59 
operator ()()60     void operator()()
61     {
62         assert(alive_ == 1);
63         assert(n_alive >= 1);
64         op_run = true;
65     }
66 
operator ()(int i,double j)67     void operator()(int i, double j)
68     {
69         assert(alive_ == 1);
70         assert(n_alive >= 1);
71         assert(i == 5);
72         assert(j == 5.5);
73         op_run = true;
74     }
75 };
76 
77 int G::n_alive = 0;
78 bool G::op_run = false;
79 
80 #if TEST_STD_VER >= 11
81 
82 class MoveOnly
83 {
84     MoveOnly(const MoveOnly&);
85 public:
MoveOnly()86     MoveOnly() {}
MoveOnly(MoveOnly &&)87     MoveOnly(MoveOnly&&) {}
88 
operator ()(MoveOnly &&)89     void operator()(MoveOnly&&)
90     {
91     }
92 };
93 
94 #endif
95 
main()96 int main()
97 {
98     {
99         std::thread t(f);
100         t.join();
101         assert(f_run == true);
102     }
103     f_run = false;
104     {
105         try
106         {
107             throw_one = 0;
108             std::thread t(f);
109             assert(false);
110         }
111         catch (...)
112         {
113             throw_one = 0xFFFF;
114             assert(!f_run);
115         }
116     }
117     {
118         assert(G::n_alive == 0);
119         assert(!G::op_run);
120         std::thread t((G()));
121         t.join();
122         assert(G::n_alive == 0);
123         assert(G::op_run);
124     }
125     G::op_run = false;
126     {
127         try
128         {
129             throw_one = 0;
130             assert(G::n_alive == 0);
131             assert(!G::op_run);
132             std::thread t((G()));
133             assert(false);
134         }
135         catch (...)
136         {
137             throw_one = 0xFFFF;
138             assert(G::n_alive == 0);
139             assert(!G::op_run);
140         }
141     }
142 #if TEST_STD_VER >= 11
143     {
144         assert(G::n_alive == 0);
145         assert(!G::op_run);
146         std::thread t(G(), 5, 5.5);
147         t.join();
148         assert(G::n_alive == 0);
149         assert(G::op_run);
150     }
151     {
152         std::thread t = std::thread(MoveOnly(), MoveOnly());
153         t.join();
154     }
155 #endif
156 }
157