1bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===----------------------------------------------------------------------===//
2bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
3f5256e16dfc425c1d466f6308d4026d529ce9e0bHoward Hinnant//                     The LLVM Compiler Infrastructure
4bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
5b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// This file is dual licensed under the MIT and the University of Illinois Open
6b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// Source Licenses. See LICENSE.TXT for details.
7bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
8bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===----------------------------------------------------------------------===//
98d86b2e6867297fb2109824c67c50de67f3a31f2Jonathan Roelofs//
108d86b2e6867297fb2109824c67c50de67f3a31f2Jonathan Roelofs// UNSUPPORTED: libcpp-has-no-threads
11bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
12bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// <thread>
13bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
14bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// class thread
15bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
16bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// template <class F, class ...Args> thread(F&& f, Args&&... args);
17bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
1807a4bec1dd600078aa8ec64f5aaeae9a7cc5d7d8Eric Fiselier// UNSUPPORTED: sanitizer-new-delete
1969697c8506fb47fe160c0327caa2cd8bd8f6adedEric Fiselier
20bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include <thread>
21bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include <new>
22e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier#include <atomic>
23bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include <cstdlib>
24bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include <cassert>
25bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
26286e0a491b5d3cfd73b2ae3b42cf16b9181904e7Eric Fiselier#include "test_macros.h"
27286e0a491b5d3cfd73b2ae3b42cf16b9181904e7Eric Fiselier
28e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselierstd::atomic<unsigned> throw_one(0xFFFF);
29e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselierstd::atomic<unsigned> outstanding_new(0);
30e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier
31bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
3212a450ff3b05407eb5cd6a433edd5ab2f28c44feEric Fiseliervoid* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
33bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
34bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    if (throw_one == 0)
35e3a71a295ed9412bb34ab125c98380498a608b1aAsiri Rathnayake        TEST_THROW(std::bad_alloc());
36bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    --throw_one;
37e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier    ++outstanding_new;
38f5b30213b6f14517baf4980ae696b4f37ba16575Eric Fiselier    void* ret = std::malloc(s);
39f5b30213b6f14517baf4980ae696b4f37ba16575Eric Fiselier    if (!ret) std::abort(); // placate MSVC's unchecked malloc warning
40f5b30213b6f14517baf4980ae696b4f37ba16575Eric Fiselier    return ret;
41bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
42bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
4312a450ff3b05407eb5cd6a433edd5ab2f28c44feEric Fiseliervoid  operator delete(void* p) TEST_NOEXCEPT
44bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
45e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier    --outstanding_new;
46bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    std::free(p);
47bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
48bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
49bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantbool f_run = false;
50bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
51bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid f()
52bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
53bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    f_run = true;
54bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
55bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
56bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantclass G
57bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
58bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    int alive_;
59bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantpublic:
60bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    static int n_alive;
61bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    static bool op_run;
62bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
63bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    G() : alive_(1) {++n_alive;}
64bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    G(const G& g) : alive_(g.alive_) {++n_alive;}
65bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    ~G() {alive_ = 0; --n_alive;}
66bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
67bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    void operator()()
68bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
69bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(alive_ == 1);
70bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(n_alive >= 1);
71bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        op_run = true;
72bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
73bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
74bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    void operator()(int i, double j)
75bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
76bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(alive_ == 1);
77bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(n_alive >= 1);
78bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(i == 5);
79bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(j == 5.5);
80bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        op_run = true;
81bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
82bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant};
83bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
84bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantint G::n_alive = 0;
85bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantbool G::op_run = false;
86bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
87286e0a491b5d3cfd73b2ae3b42cf16b9181904e7Eric Fiselier#if TEST_STD_VER >= 11
88656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant
89656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnantclass MoveOnly
90656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant{
91656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant    MoveOnly(const MoveOnly&);
92656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnantpublic:
93656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant    MoveOnly() {}
94656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant    MoveOnly(MoveOnly&&) {}
95656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant
96656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant    void operator()(MoveOnly&&)
97656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant    {
98656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant    }
99656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant};
100656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant
101656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant#endif
102656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant
103e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier// Test throwing std::bad_alloc
104e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier//-----------------------------
105e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier// Concerns:
106e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier//  A Each allocation performed during thread construction should be performed
107e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier//    in the parent thread so that std::terminate is not called if
108e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier//    std::bad_alloc is thrown by new.
10916e2ba19dfffdcf9bba202eb8a27fd79e3d15303Stephan T. Lavavej//  B std::thread's constructor should properly handle exceptions and not leak
110e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier//    memory.
111e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier// Plan:
112e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier//  1 Create a thread and count the number of allocations, 'N', it performs.
113e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier//  2 For each allocation performed run a test where that allocation throws.
114e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier//    2.1 check that the exception can be caught in the parent thread.
115e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier//    2.2 Check that the functor has not been called.
116e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier//    2.3 Check that no memory allocated by the creation of the thread is leaked.
117e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier//  3 Finally check that a thread runs successfully if we throw after 'N+1'
118e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier//    allocations.
119e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiseliervoid test_throwing_new_during_thread_creation() {
120e3a71a295ed9412bb34ab125c98380498a608b1aAsiri Rathnayake#ifndef TEST_HAS_NO_EXCEPTIONS
121e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier    throw_one = 0xFFF;
122bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
123bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        std::thread t(f);
124bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        t.join();
125bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
126e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier    const int numAllocs = 0xFFF - throw_one;
127e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier    // i <= numAllocs means the last iteration is expected not to throw.
128e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier    for (int i=0; i <= numAllocs; ++i) {
129e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier        throw_one = i;
130e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier        f_run = false;
131e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier        unsigned old_outstanding = outstanding_new;
132e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier        try {
133bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            std::thread t(f);
134e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier            assert(i == numAllocs); // Only final iteration will not throw.
135e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier            t.join();
136e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier            assert(f_run);
137e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier        } catch (std::bad_alloc const&) {
138e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier            assert(i < numAllocs);
139e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier            assert(!f_run); // (2.2)
140bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        }
141e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier        assert(old_outstanding == outstanding_new); // (2.3)
142e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier    }
143e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier    f_run = false;
144e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier    throw_one = 0xFFF;
145e3a71a295ed9412bb34ab125c98380498a608b1aAsiri Rathnayake#endif
146e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier}
147e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier
148e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselierint main()
149e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier{
150e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier    test_throwing_new_during_thread_creation();
151e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier    {
152e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier        std::thread t(f);
153e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier        t.join();
154e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier        assert(f_run == true);
155bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
156e94c1aee2bef8ee8671d56160e2c27f9704646aeEric Fiselier
157bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
158bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(G::n_alive == 0);
159bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(!G::op_run);
160bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        std::thread t((G()));
161bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        t.join();
162bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(G::n_alive == 0);
163bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(G::op_run);
164bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
165bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    G::op_run = false;
166e3a71a295ed9412bb34ab125c98380498a608b1aAsiri Rathnayake#ifndef TEST_HAS_NO_EXCEPTIONS
167bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
168bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        try
169bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        {
170bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            throw_one = 0;
171bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            assert(G::n_alive == 0);
172bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            assert(!G::op_run);
173bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            std::thread t((G()));
174bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            assert(false);
175bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        }
176bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        catch (...)
177bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        {
178bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            throw_one = 0xFFFF;
179bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            assert(G::n_alive == 0);
180bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            assert(!G::op_run);
181bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        }
182bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
183e3a71a295ed9412bb34ab125c98380498a608b1aAsiri Rathnayake#endif
184286e0a491b5d3cfd73b2ae3b42cf16b9181904e7Eric Fiselier#if TEST_STD_VER >= 11
185bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
186bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(G::n_alive == 0);
187bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(!G::op_run);
188bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        std::thread t(G(), 5, 5.5);
189bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        t.join();
190bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(G::n_alive == 0);
191bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        assert(G::op_run);
192bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
193656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant    {
194656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant        std::thread t = std::thread(MoveOnly(), MoveOnly());
195656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant        t.join();
196656bdc3667f65f4d9c2bd2252c0d62122b97b5a0Howard Hinnant    }
197286e0a491b5d3cfd73b2ae3b42cf16b9181904e7Eric Fiselier#endif
198bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
199