F.pass.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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. // <thread>
  12. // class thread
  13. // template <class F, class ...Args> thread(F&& f, Args&&... args);
  14. // UNSUPPORTED: sanitizer-new-delete
  15. #include <thread>
  16. #include <new>
  17. #include <atomic>
  18. #include <cstdlib>
  19. #include <cassert>
  20. #include "test_macros.h"
  21. std::atomic<unsigned> throw_one(0xFFFF);
  22. std::atomic<unsigned> outstanding_new(0);
  23. void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
  24. {
  25. if (throw_one == 0)
  26. TEST_THROW(std::bad_alloc());
  27. --throw_one;
  28. ++outstanding_new;
  29. void* ret = std::malloc(s);
  30. if (!ret) std::abort(); // placate MSVC's unchecked malloc warning
  31. return ret;
  32. }
  33. void operator delete(void* p) TEST_NOEXCEPT
  34. {
  35. --outstanding_new;
  36. std::free(p);
  37. }
  38. bool f_run = false;
  39. void f()
  40. {
  41. f_run = true;
  42. }
  43. class G
  44. {
  45. int alive_;
  46. public:
  47. static int n_alive;
  48. static bool op_run;
  49. G() : alive_(1) {++n_alive;}
  50. G(const G& g) : alive_(g.alive_) {++n_alive;}
  51. ~G() {alive_ = 0; --n_alive;}
  52. void operator()()
  53. {
  54. assert(alive_ == 1);
  55. assert(n_alive >= 1);
  56. op_run = true;
  57. }
  58. void operator()(int i, double j)
  59. {
  60. assert(alive_ == 1);
  61. assert(n_alive >= 1);
  62. assert(i == 5);
  63. assert(j == 5.5);
  64. op_run = true;
  65. }
  66. };
  67. int G::n_alive = 0;
  68. bool G::op_run = false;
  69. #if TEST_STD_VER >= 11
  70. class MoveOnly
  71. {
  72. MoveOnly(const MoveOnly&);
  73. public:
  74. MoveOnly() {}
  75. MoveOnly(MoveOnly&&) {}
  76. void operator()(MoveOnly&&)
  77. {
  78. }
  79. };
  80. #endif
  81. // Test throwing std::bad_alloc
  82. //-----------------------------
  83. // Concerns:
  84. // A Each allocation performed during thread construction should be performed
  85. // in the parent thread so that std::terminate is not called if
  86. // std::bad_alloc is thrown by new.
  87. // B std::threads constructor should properly handle exceptions and not leak
  88. // memory.
  89. // Plan:
  90. // 1 Create a thread and count the number of allocations, 'N', it performs.
  91. // 2 For each allocation performed run a test where that allocation throws.
  92. // 2.1 check that the exception can be caught in the parent thread.
  93. // 2.2 Check that the functor has not been called.
  94. // 2.3 Check that no memory allocated by the creation of the thread is leaked.
  95. // 3 Finally check that a thread runs successfully if we throw after 'N+1'
  96. // allocations.
  97. void test_throwing_new_during_thread_creation() {
  98. #ifndef TEST_HAS_NO_EXCEPTIONS
  99. throw_one = 0xFFF;
  100. {
  101. std::thread t(f);
  102. t.join();
  103. }
  104. const int numAllocs = 0xFFF - throw_one;
  105. // i <= numAllocs means the last iteration is expected not to throw.
  106. for (int i=0; i <= numAllocs; ++i) {
  107. throw_one = i;
  108. f_run = false;
  109. unsigned old_outstanding = outstanding_new;
  110. try {
  111. std::thread t(f);
  112. assert(i == numAllocs); // Only final iteration will not throw.
  113. t.join();
  114. assert(f_run);
  115. } catch (std::bad_alloc const&) {
  116. assert(i < numAllocs);
  117. assert(!f_run); // (2.2)
  118. }
  119. assert(old_outstanding == outstanding_new); // (2.3)
  120. }
  121. f_run = false;
  122. throw_one = 0xFFF;
  123. #endif
  124. }
  125. int main()
  126. {
  127. test_throwing_new_during_thread_creation();
  128. {
  129. std::thread t(f);
  130. t.join();
  131. assert(f_run == true);
  132. }
  133. {
  134. assert(G::n_alive == 0);
  135. assert(!G::op_run);
  136. std::thread t((G()));
  137. t.join();
  138. assert(G::n_alive == 0);
  139. assert(G::op_run);
  140. }
  141. G::op_run = false;
  142. #ifndef TEST_HAS_NO_EXCEPTIONS
  143. {
  144. try
  145. {
  146. throw_one = 0;
  147. assert(G::n_alive == 0);
  148. assert(!G::op_run);
  149. std::thread t((G()));
  150. assert(false);
  151. }
  152. catch (...)
  153. {
  154. throw_one = 0xFFFF;
  155. assert(G::n_alive == 0);
  156. assert(!G::op_run);
  157. }
  158. }
  159. #endif
  160. #if TEST_STD_VER >= 11
  161. {
  162. assert(G::n_alive == 0);
  163. assert(!G::op_run);
  164. std::thread t(G(), 5, 5.5);
  165. t.join();
  166. assert(G::n_alive == 0);
  167. assert(G::op_run);
  168. }
  169. {
  170. std::thread t = std::thread(MoveOnly(), MoveOnly());
  171. t.join();
  172. }
  173. #endif
  174. }