1 #include <doctest/doctest.h>
2 
3 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
4 
5 DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
6 #include <thread>
7 #include <mutex>
8 #include <exception>
9 #include <stdexcept>
10 DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
11 
12 DOCTEST_MSVC_SUPPRESS_WARNING(4626) // assignment operator was implicitly defined as deleted
13 
14 TEST_CASE("threads...") {
__anon84a86de90102(int value) 15     auto call_from_thread = [](int value) {
16         INFO("print me!");
17         // one of these has to fail
18         CHECK(value == 1);
19         CHECK(value == 2);
20     };
21 
22     int data_1 = 1;
23     int data_2 = 2;
24     CAPTURE(data_1); // will not be used for assertions in other threads
25 
26     // subcases have to be used only in the main thread (where the test runner is)
27     SUBCASE("test runner thread") {
28         call_from_thread(data_1);
29     }
30 
31     // normal threads which are assumed not to throw
32     SUBCASE("spawned threads") {
33         std::thread t1(call_from_thread, data_1);
34         std::thread t2(call_from_thread, data_2);
35 
36         t1.join();
37         t2.join();
38     }
39 
40     // exceptions from threads (that includes failing REQUIRE asserts) have to be handled explicitly
41     SUBCASE("spawned threads with exception propagation") {
42         std::exception_ptr exception_ptr = nullptr;
43         std::mutex         mutex;
44 
__anon84a86de90202() 45         auto might_throw = [&]() {
46             try {
47                 REQUIRE(1 == 1);
48                 REQUIRE(1 == 2); // will fail and throw an exception
49                 MESSAGE("not reached!");
50             } catch(...) {
51                 // make sure there are no races when dealing with the exception ptr
52                 std::lock_guard<std::mutex> lock(mutex);
53 
54                 // set the exception pointer in case of an exception - might overwrite
55                 // another exception but here we care about propagating any exception - not all
56                 exception_ptr = std::current_exception();
57             }
58         };
59         std::thread t1(might_throw);
60         std::thread t2(might_throw);
61 
62         t1.join();
63         t2.join();
64 
65         // if any thread has thrown an exception - rethrow it
66         if(exception_ptr)
67             std::rethrow_exception(exception_ptr);
68     }
69 }
70 
71 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
72