summaryrefslogtreecommitdiff
path: root/test/std/thread/thread.threads/thread.thread.class
diff options
context:
space:
mode:
Diffstat (limited to 'test/std/thread/thread.threads/thread.thread.class')
-rw-r--r--test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp70
-rw-r--r--test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/constr.fail.cpp2
-rw-r--r--test/std/thread/thread.threads/thread.thread.class/thread.thread.member/detach.pass.cpp17
-rw-r--r--test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp23
-rw-r--r--test/std/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp54
-rw-r--r--test/std/thread/thread.threads/thread.thread.class/types.pass.cpp27
6 files changed, 95 insertions, 98 deletions
diff --git a/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp b/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
index 3de15af8929b..5dd6a40a0eb7 100644
--- a/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
+++ b/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
@@ -20,23 +20,30 @@
#include <thread>
#include <new>
+#include <atomic>
#include <cstdlib>
#include <cassert>
#include "test_macros.h"
-unsigned throw_one = 0xFFFF;
+std::atomic<unsigned> throw_one(0xFFFF);
+std::atomic<unsigned> outstanding_new(0);
+
void* operator new(std::size_t s) throw(std::bad_alloc)
{
if (throw_one == 0)
throw std::bad_alloc();
--throw_one;
- return std::malloc(s);
+ ++outstanding_new;
+ void* ret = std::malloc(s);
+ if (!ret) std::abort(); // placate MSVC's unchecked malloc warning
+ return ret;
}
void operator delete(void* p) throw()
{
+ --outstanding_new;
std::free(p);
}
@@ -94,27 +101,58 @@ public:
#endif
-int main()
-{
+// Test throwing std::bad_alloc
+//-----------------------------
+// Concerns:
+// A Each allocation performed during thread construction should be performed
+// in the parent thread so that std::terminate is not called if
+// std::bad_alloc is thrown by new.
+// B std::threads constructor should properly handle exceptions and not leak
+// memory.
+// Plan:
+// 1 Create a thread and count the number of allocations, 'N', it performs.
+// 2 For each allocation performed run a test where that allocation throws.
+// 2.1 check that the exception can be caught in the parent thread.
+// 2.2 Check that the functor has not been called.
+// 2.3 Check that no memory allocated by the creation of the thread is leaked.
+// 3 Finally check that a thread runs successfully if we throw after 'N+1'
+// allocations.
+void test_throwing_new_during_thread_creation() {
+ throw_one = 0xFFF;
{
std::thread t(f);
t.join();
- assert(f_run == true);
}
- f_run = false;
- {
- try
- {
- throw_one = 0;
+ const int numAllocs = 0xFFF - throw_one;
+ // i <= numAllocs means the last iteration is expected not to throw.
+ for (int i=0; i <= numAllocs; ++i) {
+ throw_one = i;
+ f_run = false;
+ unsigned old_outstanding = outstanding_new;
+ try {
std::thread t(f);
- assert(false);
- }
- catch (...)
- {
- throw_one = 0xFFFF;
- assert(!f_run);
+ assert(i == numAllocs); // Only final iteration will not throw.
+ t.join();
+ assert(f_run);
+ } catch (std::bad_alloc const&) {
+ assert(i < numAllocs);
+ assert(!f_run); // (2.2)
}
+ assert(old_outstanding == outstanding_new); // (2.3)
+ }
+ f_run = false;
+ throw_one = 0xFFF;
+}
+
+int main()
+{
+ test_throwing_new_during_thread_creation();
+ {
+ std::thread t(f);
+ t.join();
+ assert(f_run == true);
}
+
{
assert(G::n_alive == 0);
assert(!G::op_run);
diff --git a/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/constr.fail.cpp b/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/constr.fail.cpp
index a331add96263..54fc0b80280c 100644
--- a/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/constr.fail.cpp
+++ b/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/constr.fail.cpp
@@ -12,7 +12,7 @@
// class thread
// template <class _Fp, class ..._Args,
// explicit thread(_Fp&& __f, _Args&&... __args);
-// This constructor shall not participate in overload resolution
+// This constructor shall not participate in overload resolution
// if decay<F>::type is the same type as std::thread.
diff --git a/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/detach.pass.cpp b/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/detach.pass.cpp
index 726395d99044..3dd7c6a6014c 100644
--- a/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/detach.pass.cpp
+++ b/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/detach.pass.cpp
@@ -17,8 +17,11 @@
#include <thread>
#include <atomic>
+#include <system_error>
#include <cassert>
+#include "test_macros.h"
+
std::atomic_bool done(false);
class G
@@ -57,6 +60,8 @@ public:
int G::n_alive = 0;
bool G::op_run = false;
+void foo() {}
+
int main()
{
{
@@ -70,4 +75,16 @@ int main()
assert(G::n_alive == 1);
}
assert(G::n_alive == 0);
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ std::thread t0(foo);
+ assert(t0.joinable());
+ t0.detach();
+ assert(!t0.joinable());
+ try {
+ t0.detach();
+ } catch (std::system_error const&) {
+ }
+ }
+#endif
}
diff --git a/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp b/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp
index 0512e49dcb33..f0c3ef74c9ab 100644
--- a/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp
+++ b/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp
@@ -19,6 +19,9 @@
#include <new>
#include <cstdlib>
#include <cassert>
+#include <system_error>
+
+#include "test_macros.h"
class G
{
@@ -42,6 +45,8 @@ public:
int G::n_alive = 0;
bool G::op_run = false;
+void foo() {}
+
int main()
{
{
@@ -50,5 +55,23 @@ int main()
assert(t0.joinable());
t0.join();
assert(!t0.joinable());
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ t0.join();
+ assert(false);
+ } catch (std::system_error const&) {
+ }
+#endif
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ std::thread t0(foo);
+ t0.detach();
+ try {
+ t0.join();
+ assert(false);
+ } catch (std::system_error const&) {
+ }
}
+#endif
}
diff --git a/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp b/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp
deleted file mode 100644
index c8807a965c44..000000000000
--- a/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: libcpp-has-no-threads
-
-// <thread>
-
-// class thread
-
-// native_handle_type native_handle();
-
-#include <thread>
-#include <new>
-#include <cstdlib>
-#include <cassert>
-
-class G
-{
- int alive_;
-public:
- static int n_alive;
- static bool op_run;
-
- G() : alive_(1) {++n_alive;}
- G(const G& g) : alive_(g.alive_) {++n_alive;}
- ~G() {alive_ = 0; --n_alive;}
-
- void operator()()
- {
- assert(alive_ == 1);
- assert(n_alive >= 1);
- op_run = true;
- }
-};
-
-int G::n_alive = 0;
-bool G::op_run = false;
-
-int main()
-{
- {
- G g;
- std::thread t0(g);
- pthread_t pid = t0.native_handle();
- assert(pid != 0);
- t0.join();
- }
-}
diff --git a/test/std/thread/thread.threads/thread.thread.class/types.pass.cpp b/test/std/thread/thread.threads/thread.thread.class/types.pass.cpp
deleted file mode 100644
index a5bf77031cca..000000000000
--- a/test/std/thread/thread.threads/thread.thread.class/types.pass.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: libcpp-has-no-threads
-
-// <thread>
-
-// class thread
-// {
-// public:
-// typedef pthread_t native_handle_type;
-// ...
-// };
-
-#include <thread>
-#include <type_traits>
-
-int main()
-{
- static_assert((std::is_same<std::thread::native_handle_type, pthread_t>::value), "");
-}