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