15a83710eSEric Fiselier //===----------------------------------------------------------------------===//
25a83710eSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a83710eSEric Fiselier //
75a83710eSEric Fiselier //===----------------------------------------------------------------------===//
85a83710eSEric Fiselier //
9*a7f9895cSLouis Dionne // UNSUPPORTED: no-threads
105a83710eSEric Fiselier 
115a83710eSEric Fiselier // <thread>
125a83710eSEric Fiselier 
135a83710eSEric Fiselier // class thread
145a83710eSEric Fiselier 
155a83710eSEric Fiselier // void detach();
165a83710eSEric Fiselier 
175a83710eSEric Fiselier #include <thread>
1892499e45SEric Fiselier #include <atomic>
194efa1ad5SEric Fiselier #include <system_error>
205a83710eSEric Fiselier #include <cassert>
215a83710eSEric Fiselier 
2256462801SLouis Dionne #include "make_test_thread.h"
234efa1ad5SEric Fiselier #include "test_macros.h"
244efa1ad5SEric Fiselier 
2592499e45SEric Fiselier std::atomic_bool done(false);
26513ae185SEric Fiselier 
275a83710eSEric Fiselier class G
285a83710eSEric Fiselier {
295a83710eSEric Fiselier     int alive_;
30513ae185SEric Fiselier     bool done_;
315a83710eSEric Fiselier public:
325a83710eSEric Fiselier     static int n_alive;
335a83710eSEric Fiselier     static bool op_run;
345a83710eSEric Fiselier 
G()35513ae185SEric Fiselier     G() : alive_(1), done_(false)
36513ae185SEric Fiselier     {
37513ae185SEric Fiselier         ++n_alive;
38513ae185SEric Fiselier     }
39513ae185SEric Fiselier 
G(const G & g)40513ae185SEric Fiselier     G(const G& g) : alive_(g.alive_), done_(false)
41513ae185SEric Fiselier     {
42513ae185SEric Fiselier         ++n_alive;
43513ae185SEric Fiselier     }
~G()44513ae185SEric Fiselier     ~G()
45513ae185SEric Fiselier     {
46513ae185SEric Fiselier         alive_ = 0;
47513ae185SEric Fiselier         --n_alive;
48513ae185SEric Fiselier         if (done_) done = true;
49513ae185SEric Fiselier     }
505a83710eSEric Fiselier 
operator ()()515a83710eSEric Fiselier     void operator()()
525a83710eSEric Fiselier     {
535a83710eSEric Fiselier         assert(alive_ == 1);
545a83710eSEric Fiselier         assert(n_alive >= 1);
555a83710eSEric Fiselier         op_run = true;
56513ae185SEric Fiselier         done_ = true;
575a83710eSEric Fiselier     }
585a83710eSEric Fiselier };
595a83710eSEric Fiselier 
605a83710eSEric Fiselier int G::n_alive = 0;
615a83710eSEric Fiselier bool G::op_run = false;
625a83710eSEric Fiselier 
foo()63715ca752SMartin Storsjö void foo() { done = true; }
644efa1ad5SEric Fiselier 
main(int,char **)652df59c50SJF Bastien int main(int, char**)
665a83710eSEric Fiselier {
675a83710eSEric Fiselier     {
68513ae185SEric Fiselier         G g;
6956462801SLouis Dionne         std::thread t0 = support::make_test_thread(g);
705a83710eSEric Fiselier         assert(t0.joinable());
715a83710eSEric Fiselier         t0.detach();
725a83710eSEric Fiselier         assert(!t0.joinable());
73513ae185SEric Fiselier         while (!done) {}
745a83710eSEric Fiselier         assert(G::op_run);
75513ae185SEric Fiselier         assert(G::n_alive == 1);
765a83710eSEric Fiselier     }
77513ae185SEric Fiselier     assert(G::n_alive == 0);
78715ca752SMartin Storsjö     done = false;
79eb066bc2SEric Fiselier #ifndef TEST_HAS_NO_EXCEPTIONS
804efa1ad5SEric Fiselier     {
8156462801SLouis Dionne         std::thread t0 = support::make_test_thread(foo);
824efa1ad5SEric Fiselier         assert(t0.joinable());
834efa1ad5SEric Fiselier         t0.detach();
844efa1ad5SEric Fiselier         assert(!t0.joinable());
854efa1ad5SEric Fiselier         try {
864efa1ad5SEric Fiselier             t0.detach();
8784685fc8SEric Fiselier         } catch (std::system_error const&) {
884efa1ad5SEric Fiselier         }
89715ca752SMartin Storsjö         // Wait to make sure that the detached thread has started up.
90715ca752SMartin Storsjö         // Without this, we could exit main and start destructing global
91715ca752SMartin Storsjö         // resources that are needed when the thread starts up, while the
92715ca752SMartin Storsjö         // detached thread would start up only later.
93715ca752SMartin Storsjö         while (!done) {}
944efa1ad5SEric Fiselier     }
954efa1ad5SEric Fiselier #endif
962df59c50SJF Bastien 
972df59c50SJF Bastien   return 0;
985a83710eSEric Fiselier }
99