summaryrefslogtreecommitdiff
path: root/test/std/thread
diff options
context:
space:
mode:
Diffstat (limited to 'test/std/thread')
-rw-r--r--test/std/thread/futures/futures.async/async.pass.cpp185
-rw-r--r--test/std/thread/futures/futures.overview/future_errc.pass.cpp26
-rw-r--r--test/std/thread/futures/futures.overview/launch.pass.cpp14
-rw-r--r--test/std/thread/futures/futures.promise/copy_assign.fail.cpp2
-rw-r--r--test/std/thread/futures/futures.promise/copy_ctor.fail.cpp2
-rw-r--r--test/std/thread/futures/futures.promise/set_rvalue.pass.cpp3
-rw-r--r--test/std/thread/futures/futures.tas/types.pass.cpp29
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/assign_copy.fail.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/assign_copy.fail.cpp)3
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/assign_move.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/assign_move.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/ctor1.fail.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/ctor1.fail.cpp)5
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/ctor2.fail.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/ctor2.fail.cpp)5
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/ctor_copy.fail.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/ctor_copy.fail.cpp)3
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/ctor_default.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/ctor_default.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/ctor_func.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/ctor_func.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/ctor_func_alloc.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/ctor_move.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/ctor_move.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/dtor.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/dtor.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/get_future.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/get_future.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/make_ready_at_thread_exit.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/make_ready_at_thread_exit.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/operator.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/operator.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/reset.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/reset.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.task/futures.task.members/swap.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.members/swap.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.task/futures.task.nonmembers/swap.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.nonmembers/swap.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.task/futures.task.nonmembers/uses_allocator.pass.cpp (renamed from test/std/thread/futures/futures.tas/futures.task.nonmembers/uses_allocator.pass.cpp)0
-rw-r--r--test/std/thread/futures/futures.unique_future/copy_assign.fail.cpp2
-rw-r--r--test/std/thread/futures/futures.unique_future/copy_ctor.fail.cpp2
-rw-r--r--test/std/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp29
-rw-r--r--test/std/thread/thread.condition/version.pass.cpp22
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.fail.cpp32
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_adopt_lock.pass.cpp62
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_assign.fail.cpp44
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_copy.fail.cpp41
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex.fail.cpp47
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex.pass.cpp115
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex_cxx03.pass.cpp (renamed from test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.recursive/native_handle.pass.cpp)18
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_types.pass.cpp78
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/copy_assign.fail.cpp9
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/copy_ctor.fail.cpp7
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp26
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_ctor.pass.cpp22
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp20
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp17
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.fail.cpp12
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.fail.cpp10
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp27
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp23
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp18
-rw-r--r--test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp17
-rw-r--r--test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.pass.cpp27
-rw-r--r--test/std/thread/thread.mutex/thread.mutex.requirements/thread.shared_mutex.requirements/thread.shared_mutex.class/assign.fail.cpp1
-rw-r--r--test/std/thread/thread.mutex/thread.mutex.requirements/thread.shared_mutex.requirements/thread.shared_mutex.class/copy.fail.cpp1
-rw-r--r--test/std/thread/thread.mutex/thread.mutex.requirements/thread.sharedtimedmutex.requirements/thread.sharedtimedmutex.class/assign.fail.cpp5
-rw-r--r--test/std/thread/thread.mutex/thread.mutex.requirements/thread.sharedtimedmutex.requirements/thread.sharedtimedmutex.class/copy.fail.cpp5
-rw-r--r--test/std/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp6
-rw-r--r--test/std/thread/thread.mutex/version.pass.cpp20
-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
-rw-r--r--test/std/thread/thread.threads/version.pass.cpp22
62 files changed, 766 insertions, 491 deletions
diff --git a/test/std/thread/futures/futures.async/async.pass.cpp b/test/std/thread/futures/futures.async/async.pass.cpp
index 2c1313b7a2f0f..5cb824d482240 100644
--- a/test/std/thread/futures/futures.async/async.pass.cpp
+++ b/test/std/thread/futures/futures.async/async.pass.cpp
@@ -21,15 +21,22 @@
// future<typename result_of<F(Args...)>::type>
// async(launch policy, F&& f, Args&&... args);
+
#include <future>
+#include <atomic>
#include <memory>
#include <cassert>
+#include "test_macros.h"
+
typedef std::chrono::high_resolution_clock Clock;
typedef std::chrono::milliseconds ms;
+std::atomic_bool invoked = ATOMIC_VAR_INIT(false);
+
int f0()
{
+ invoked = true;
std::this_thread::sleep_for(ms(200));
return 3;
}
@@ -38,163 +45,109 @@ int i = 0;
int& f1()
{
+ invoked = true;
std::this_thread::sleep_for(ms(200));
return i;
}
void f2()
{
+ invoked = true;
std::this_thread::sleep_for(ms(200));
}
-std::unique_ptr<int> f3(int i)
+std::unique_ptr<int> f3(int j)
{
+ invoked = true;
std::this_thread::sleep_for(ms(200));
- return std::unique_ptr<int>(new int(i));
+ return std::unique_ptr<int>(new int(j));
}
std::unique_ptr<int> f4(std::unique_ptr<int>&& p)
{
+ invoked = true;
std::this_thread::sleep_for(ms(200));
return std::move(p);
}
-void f5(int i)
+void f5(int j)
{
std::this_thread::sleep_for(ms(200));
- throw i;
+ throw j;
}
-int main()
-{
- {
- std::future<int> f = std::async(f0);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- assert(f.get() == 3);
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 < ms(100));
- }
- {
- std::future<int> f = std::async(std::launch::async, f0);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- assert(f.get() == 3);
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 < ms(100));
- }
- {
- std::future<int> f = std::async(std::launch::any, f0);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- assert(f.get() == 3);
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 < ms(100));
- }
- {
- std::future<int> f = std::async(std::launch::deferred, f0);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- assert(f.get() == 3);
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 > ms(100));
- }
+template <class Ret, class CheckLamdba, class ...Args>
+void test(CheckLamdba&& getAndCheckFn, bool IsDeferred, Args&&... args) {
+ // Reset global state.
+ invoked = false;
- {
- std::future<int&> f = std::async(f1);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- assert(&f.get() == &i);
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 < ms(100));
- }
- {
- std::future<int&> f = std::async(std::launch::async, f1);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- assert(&f.get() == &i);
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 < ms(100));
- }
- {
- std::future<int&> f = std::async(std::launch::any, f1);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- assert(&f.get() == &i);
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 < ms(100));
- }
- {
- std::future<int&> f = std::async(std::launch::deferred, f1);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- assert(&f.get() == &i);
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 > ms(100));
- }
+ // Create the future and wait
+ std::future<Ret> f = std::async(std::forward<Args>(args)...);
+ std::this_thread::sleep_for(ms(300));
- {
- std::future<void> f = std::async(f2);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- f.get();
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 < ms(100));
- }
- {
- std::future<void> f = std::async(std::launch::async, f2);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- f.get();
- Clock::time_point t1 = Clock::now();
+ // Check that deferred async's have not invoked the function.
+ assert(invoked == !IsDeferred);
+
+ // Time the call to f.get() and check that the returned value matches
+ // what is expected.
+ Clock::time_point t0 = Clock::now();
+ assert(getAndCheckFn(f));
+ Clock::time_point t1 = Clock::now();
+
+ // If the async is deferred it should take more than 100ms, otherwise
+ // it should take less than 100ms.
+ if (IsDeferred) {
+ assert(t1-t0 > ms(100));
+ } else {
assert(t1-t0 < ms(100));
}
+}
+
+int main()
+{
+ // The default launch policy is implementation defined. libc++ defines
+ // it to be std::launch::async.
+ bool DefaultPolicyIsDeferred = false;
+ bool DPID = DefaultPolicyIsDeferred;
+
+ std::launch AnyPolicy = std::launch::async | std::launch::deferred;
+ LIBCPP_ASSERT(AnyPolicy == std::launch::any);
+
{
- std::future<void> f = std::async(std::launch::any, f2);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- f.get();
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 < ms(100));
+ auto checkInt = [](std::future<int>& f) { return f.get() == 3; };
+ test<int>(checkInt, DPID, f0);
+ test<int>(checkInt, false, std::launch::async, f0);
+ test<int>(checkInt, true, std::launch::deferred, f0);
+ test<int>(checkInt, DPID, AnyPolicy, f0);
}
{
- std::future<void> f = std::async(std::launch::deferred, f2);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- f.get();
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 > ms(100));
+ auto checkIntRef = [&](std::future<int&>& f) { return &f.get() == &i; };
+ test<int&>(checkIntRef, DPID, f1);
+ test<int&>(checkIntRef, false, std::launch::async, f1);
+ test<int&>(checkIntRef, true, std::launch::deferred, f1);
+ test<int&>(checkIntRef, DPID, AnyPolicy, f1);
}
-
{
- std::future<std::unique_ptr<int>> f = std::async(f3, 3);
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- assert(*f.get() == 3);
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 < ms(100));
+ auto checkVoid = [](std::future<void>& f) { f.get(); return true; };
+ test<void>(checkVoid, DPID, f2);
+ test<void>(checkVoid, false, std::launch::async, f2);
+ test<void>(checkVoid, true, std::launch::deferred, f2);
+ test<void>(checkVoid, DPID, AnyPolicy, f2);
}
-
{
- std::future<std::unique_ptr<int>> f =
- std::async(f4, std::unique_ptr<int>(new int(3)));
- std::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- assert(*f.get() == 3);
- Clock::time_point t1 = Clock::now();
- assert(t1-t0 < ms(100));
+ using Ret = std::unique_ptr<int>;
+ auto checkUPtr = [](std::future<Ret>& f) { return *f.get() == 3; };
+ test<Ret>(checkUPtr, DPID, f3, 3);
+ test<Ret>(checkUPtr, DPID, f4, std::unique_ptr<int>(new int(3)));
}
-
{
std::future<void> f = std::async(f5, 3);
std::this_thread::sleep_for(ms(300));
- try { f.get(); assert (false); } catch ( int ex ) {}
+ try { f.get(); assert (false); } catch ( int ) {}
}
-
{
std::future<void> f = std::async(std::launch::deferred, f5, 3);
std::this_thread::sleep_for(ms(300));
- try { f.get(); assert (false); } catch ( int ex ) {}
+ try { f.get(); assert (false); } catch ( int ) {}
}
-
}
diff --git a/test/std/thread/futures/futures.overview/future_errc.pass.cpp b/test/std/thread/futures/futures.overview/future_errc.pass.cpp
index 1e6fcb76a0e73..06397487a7344 100644
--- a/test/std/thread/futures/futures.overview/future_errc.pass.cpp
+++ b/test/std/thread/futures/futures.overview/future_errc.pass.cpp
@@ -9,22 +9,32 @@
//
// UNSUPPORTED: libcpp-has-no-threads
+// UNSUPPORTED: c++98, c++03
+// Libc++'s enum class emulation does not allow static_cast<Enum>(0) to work.
+
// <future>
// enum class future_errc
// {
-// future_already_retrieved = 1,
-// promise_already_satisfied,
-// no_state
-// broken_promise,
+// broken_promise = implementation-defined,
+// future_already_retrieved = implementation-defined,
+// promise_already_satisfied = implementation-defined,
+// no_state = implementation-defined
// };
#include <future>
int main()
{
- static_assert(static_cast<int>(std::future_errc::future_already_retrieved) == 1, "");
- static_assert(static_cast<int>(std::future_errc::promise_already_satisfied) == 2, "");
- static_assert(static_cast<int>(std::future_errc::no_state) == 3, "");
- static_assert(static_cast<int>(std::future_errc::broken_promise) == 4, "");
+ static_assert(std::future_errc::broken_promise != std::future_errc::future_already_retrieved, "");
+ static_assert(std::future_errc::broken_promise != std::future_errc::promise_already_satisfied, "");
+ static_assert(std::future_errc::broken_promise != std::future_errc::no_state, "");
+ static_assert(std::future_errc::future_already_retrieved != std::future_errc::promise_already_satisfied, "");
+ static_assert(std::future_errc::future_already_retrieved != std::future_errc::no_state, "");
+ static_assert(std::future_errc::promise_already_satisfied != std::future_errc::no_state, "");
+
+ static_assert(std::future_errc::broken_promise != static_cast<std::future_errc>(0), "");
+ static_assert(std::future_errc::future_already_retrieved != static_cast<std::future_errc>(0), "");
+ static_assert(std::future_errc::promise_already_satisfied != static_cast<std::future_errc>(0), "");
+ static_assert(std::future_errc::no_state != static_cast<std::future_errc>(0), "");
}
diff --git a/test/std/thread/futures/futures.overview/launch.pass.cpp b/test/std/thread/futures/futures.overview/launch.pass.cpp
index da54f7ee67329..a26b01f67b3e7 100644
--- a/test/std/thread/futures/futures.overview/launch.pass.cpp
+++ b/test/std/thread/futures/futures.overview/launch.pass.cpp
@@ -15,28 +15,30 @@
// {
// async = 1,
// deferred = 2,
-// any = async | deferred
+// any = async | deferred /* EXTENSION */
// };
#include <future>
#include <cassert>
+#include "test_macros.h"
+
int main()
{
#ifdef _LIBCPP_HAS_NO_STRONG_ENUMS
- static_assert(static_cast<int>(std::launch::any) ==
+ LIBCPP_STATIC_ASSERT(static_cast<int>(std::launch::any) ==
(static_cast<int>(std::launch::async) | static_cast<int>(std::launch::deferred)), "");
#else
- static_assert(std::launch::any == (std::launch::async | std::launch::deferred), "");
+ LIBCPP_STATIC_ASSERT(std::launch::any == (std::launch::async | std::launch::deferred), "");
static_assert(std::launch(0) == (std::launch::async & std::launch::deferred), "");
- static_assert(std::launch::any == (std::launch::async ^ std::launch::deferred), "");
- static_assert(std::launch::deferred == ~std::launch::async, "");
+ LIBCPP_STATIC_ASSERT(std::launch::any == (std::launch::async ^ std::launch::deferred), "");
+ LIBCPP_STATIC_ASSERT(std::launch::deferred == ~std::launch::async, "");
std::launch x = std::launch::async;
x &= std::launch::deferred;
assert(x == std::launch(0));
x = std::launch::async;
x |= std::launch::deferred;
- assert(x == std::launch::any);
+ LIBCPP_ASSERT(x == std::launch::any);
x ^= std::launch::deferred;
assert(x == std::launch::async);
#endif
diff --git a/test/std/thread/futures/futures.promise/copy_assign.fail.cpp b/test/std/thread/futures/futures.promise/copy_assign.fail.cpp
index e150ba0df65a1..0311cf9b6b00f 100644
--- a/test/std/thread/futures/futures.promise/copy_assign.fail.cpp
+++ b/test/std/thread/futures/futures.promise/copy_assign.fail.cpp
@@ -6,6 +6,8 @@
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: libcpp-has-no-threads
// <future>
diff --git a/test/std/thread/futures/futures.promise/copy_ctor.fail.cpp b/test/std/thread/futures/futures.promise/copy_ctor.fail.cpp
index 34becbc1259b3..779fc5bfc7c44 100644
--- a/test/std/thread/futures/futures.promise/copy_ctor.fail.cpp
+++ b/test/std/thread/futures/futures.promise/copy_ctor.fail.cpp
@@ -6,6 +6,8 @@
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: libcpp-has-no-threads
// <future>
diff --git a/test/std/thread/futures/futures.promise/set_rvalue.pass.cpp b/test/std/thread/futures/futures.promise/set_rvalue.pass.cpp
index 9cce3f59550a2..e0c6e15d98d5e 100644
--- a/test/std/thread/futures/futures.promise/set_rvalue.pass.cpp
+++ b/test/std/thread/futures/futures.promise/set_rvalue.pass.cpp
@@ -7,8 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// XFAIL: libcpp-no-exceptions
-// UNSUPPORTED: libcpp-has-no-threads
+// UNSUPPORTED: libcpp-has-no-threads, libcpp-no-exceptions
// <future>
diff --git a/test/std/thread/futures/futures.tas/types.pass.cpp b/test/std/thread/futures/futures.tas/types.pass.cpp
deleted file mode 100644
index f7c9b223add1f..0000000000000
--- a/test/std/thread/futures/futures.tas/types.pass.cpp
+++ /dev/null
@@ -1,29 +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
-// UNSUPPORTED: c++98, c++03
-
-// <future>
-
-// template<class R, class... ArgTypes>
-// class packaged_task<R(ArgTypes...)>
-// {
-// public:
-// typedef R result_type;
-
-#include <future>
-#include <type_traits>
-
-struct A {};
-
-int main()
-{
- static_assert((std::is_same<std::packaged_task<A(int, char)>::result_type, A>::value), "");
-}
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/assign_copy.fail.cpp b/test/std/thread/futures/futures.task/futures.task.members/assign_copy.fail.cpp
index 6c6418594d007..9449e1490270d 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/assign_copy.fail.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/assign_copy.fail.cpp
@@ -6,7 +6,8 @@
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
+//
+// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++98, c++03
// <future>
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/assign_move.pass.cpp b/test/std/thread/futures/futures.task/futures.task.members/assign_move.pass.cpp
index 3f11d670bede3..3f11d670bede3 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/assign_move.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/assign_move.pass.cpp
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/ctor1.fail.cpp b/test/std/thread/futures/futures.task/futures.task.members/ctor1.fail.cpp
index 7097d428962af..6d7d734bd5e7e 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/ctor1.fail.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/ctor1.fail.cpp
@@ -6,7 +6,8 @@
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
+//
+// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++98, c++03
// <future>
@@ -14,7 +15,7 @@
// class packaged_task<R(ArgTypes...)>
// template <class F>
// packaged_task(F&& f);
-// These constructors shall not participate in overload resolution if
+// These constructors shall not participate in overload resolution if
// decay<F>::type is the same type as std::packaged_task<R(ArgTypes...)>.
#include <future>
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/ctor2.fail.cpp b/test/std/thread/futures/futures.task/futures.task.members/ctor2.fail.cpp
index feb7657bed37e..984dcdc80b32e 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/ctor2.fail.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/ctor2.fail.cpp
@@ -6,7 +6,8 @@
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
+//
+// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++98, c++03
// <future>
@@ -14,7 +15,7 @@
// class packaged_task<R(ArgTypes...)>
// template <class F, class Allocator>
// packaged_task(allocator_arg_t, const Allocator& a, F&& f);
-// These constructors shall not participate in overload resolution if
+// These constructors shall not participate in overload resolution if
// decay<F>::type is the same type as std::packaged_task<R(ArgTypes...)>.
#include <future>
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/ctor_copy.fail.cpp b/test/std/thread/futures/futures.task/futures.task.members/ctor_copy.fail.cpp
index 97624f90f3dfe..ff07db9a2e6f1 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/ctor_copy.fail.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/ctor_copy.fail.cpp
@@ -6,7 +6,8 @@
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
+//
+// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++98, c++03
// <future>
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/ctor_default.pass.cpp b/test/std/thread/futures/futures.task/futures.task.members/ctor_default.pass.cpp
index ed147d74895b1..ed147d74895b1 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/ctor_default.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/ctor_default.pass.cpp
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/ctor_func.pass.cpp b/test/std/thread/futures/futures.task/futures.task.members/ctor_func.pass.cpp
index 14ac7614bb8e5..14ac7614bb8e5 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/ctor_func.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/ctor_func.pass.cpp
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp b/test/std/thread/futures/futures.task/futures.task.members/ctor_func_alloc.pass.cpp
index 39784876b8c31..39784876b8c31 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/ctor_func_alloc.pass.cpp
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/ctor_move.pass.cpp b/test/std/thread/futures/futures.task/futures.task.members/ctor_move.pass.cpp
index d9951dca585ab..d9951dca585ab 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/ctor_move.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/ctor_move.pass.cpp
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/dtor.pass.cpp b/test/std/thread/futures/futures.task/futures.task.members/dtor.pass.cpp
index 7fafd10056490..7fafd10056490 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/dtor.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/dtor.pass.cpp
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/get_future.pass.cpp b/test/std/thread/futures/futures.task/futures.task.members/get_future.pass.cpp
index c8e5d6efd6b42..c8e5d6efd6b42 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/get_future.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/get_future.pass.cpp
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/make_ready_at_thread_exit.pass.cpp b/test/std/thread/futures/futures.task/futures.task.members/make_ready_at_thread_exit.pass.cpp
index 54ac644582486..54ac644582486 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/make_ready_at_thread_exit.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/make_ready_at_thread_exit.pass.cpp
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/operator.pass.cpp b/test/std/thread/futures/futures.task/futures.task.members/operator.pass.cpp
index 9ad1509517f64..9ad1509517f64 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/operator.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/operator.pass.cpp
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/reset.pass.cpp b/test/std/thread/futures/futures.task/futures.task.members/reset.pass.cpp
index 02a567500ee2d..02a567500ee2d 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/reset.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/reset.pass.cpp
diff --git a/test/std/thread/futures/futures.tas/futures.task.members/swap.pass.cpp b/test/std/thread/futures/futures.task/futures.task.members/swap.pass.cpp
index eb0091c8e8171..eb0091c8e8171 100644
--- a/test/std/thread/futures/futures.tas/futures.task.members/swap.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.members/swap.pass.cpp
diff --git a/test/std/thread/futures/futures.tas/futures.task.nonmembers/swap.pass.cpp b/test/std/thread/futures/futures.task/futures.task.nonmembers/swap.pass.cpp
index d90d593a75bdf..d90d593a75bdf 100644
--- a/test/std/thread/futures/futures.tas/futures.task.nonmembers/swap.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.nonmembers/swap.pass.cpp
diff --git a/test/std/thread/futures/futures.tas/futures.task.nonmembers/uses_allocator.pass.cpp b/test/std/thread/futures/futures.task/futures.task.nonmembers/uses_allocator.pass.cpp
index bbe75de7f8a9c..bbe75de7f8a9c 100644
--- a/test/std/thread/futures/futures.tas/futures.task.nonmembers/uses_allocator.pass.cpp
+++ b/test/std/thread/futures/futures.task/futures.task.nonmembers/uses_allocator.pass.cpp
diff --git a/test/std/thread/futures/futures.unique_future/copy_assign.fail.cpp b/test/std/thread/futures/futures.unique_future/copy_assign.fail.cpp
index 781c9c9d61991..d20f0c38071f4 100644
--- a/test/std/thread/futures/futures.unique_future/copy_assign.fail.cpp
+++ b/test/std/thread/futures/futures.unique_future/copy_assign.fail.cpp
@@ -6,6 +6,8 @@
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: libcpp-has-no-threads
// <future>
diff --git a/test/std/thread/futures/futures.unique_future/copy_ctor.fail.cpp b/test/std/thread/futures/futures.unique_future/copy_ctor.fail.cpp
index 0d7b5f5074d39..e1d85ac2cfdde 100644
--- a/test/std/thread/futures/futures.unique_future/copy_ctor.fail.cpp
+++ b/test/std/thread/futures/futures.unique_future/copy_ctor.fail.cpp
@@ -6,6 +6,8 @@
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: libcpp-has-no-threads
// <future>
diff --git a/test/std/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp b/test/std/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp
deleted file mode 100644
index bf28e01a0e861..0000000000000
--- a/test/std/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp
+++ /dev/null
@@ -1,29 +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
-
-// <condition_variable>
-
-// class condition_variable;
-
-// typedef pthread_cond_t* native_handle_type;
-// native_handle_type native_handle();
-
-#include <condition_variable>
-#include <cassert>
-
-int main()
-{
- static_assert((std::is_same<std::condition_variable::native_handle_type,
- pthread_cond_t*>::value), "");
- std::condition_variable cv;
- std::condition_variable::native_handle_type h = cv.native_handle();
- assert(h != nullptr);
-}
diff --git a/test/std/thread/thread.condition/version.pass.cpp b/test/std/thread/thread.condition/version.pass.cpp
deleted file mode 100644
index 12a775e833982..0000000000000
--- a/test/std/thread/thread.condition/version.pass.cpp
+++ /dev/null
@@ -1,22 +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
-
-// <condition_variable>
-
-#include <condition_variable>
-
-#ifndef _LIBCPP_VERSION
-#error _LIBCPP_VERSION not defined
-#endif
-
-int main()
-{
-}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.fail.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.fail.cpp
index 246eb935c995d..520c9730bdf7a 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.fail.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.fail.cpp
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+// UNSUPPORTED: libcpp-has-no-threads
+
// <mutex>
// template <class Mutex> class lock_guard;
@@ -14,35 +16,9 @@
// explicit lock_guard(mutex_type& m);
#include <mutex>
-#include <thread>
-#include <cstdlib>
-#include <cassert>
-
-std::mutex m;
-
-typedef std::chrono::system_clock Clock;
-typedef Clock::time_point time_point;
-typedef Clock::duration duration;
-typedef std::chrono::milliseconds ms;
-typedef std::chrono::nanoseconds ns;
-
-void f()
-{
- time_point t0 = Clock::now();
- time_point t1;
- {
- std::lock_guard<std::mutex> lg = m;
- t1 = Clock::now();
- }
- ns d = t1 - t0 - ms(250);
- assert(d < ns(2500000)); // within 2.5ms
-}
int main()
{
- m.lock();
- std::thread t(f);
- std::this_thread::sleep_for(ms(250));
- m.unlock();
- t.join();
+ std::mutex m;
+ std::lock_guard<std::mutex> lg = m; // expected-error{{no viable conversion}}
}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_adopt_lock.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_adopt_lock.pass.cpp
new file mode 100644
index 0000000000000..840af6788d04f
--- /dev/null
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_adopt_lock.pass.cpp
@@ -0,0 +1,62 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: c++98, c++03
+
+// <mutex>
+
+// template <class ...Mutex> class lock_guard;
+
+// lock_guard(Mutex&..., adopt_lock_t);
+
+#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
+#include <mutex>
+#include <cassert>
+
+struct TestMutex {
+ bool locked = false;
+ TestMutex() = default;
+
+ void lock() { assert(!locked); locked = true; }
+ bool try_lock() { if (locked) return false; locked = true; return true; }
+ void unlock() { assert(locked); locked = false; }
+
+ TestMutex(TestMutex const&) = delete;
+ TestMutex& operator=(TestMutex const&) = delete;
+};
+
+int main()
+{
+ {
+ using LG = std::lock_guard<>;
+ LG lg(std::adopt_lock);
+ }
+ {
+ TestMutex m1, m2;
+ using LG = std::lock_guard<TestMutex, TestMutex>;
+ m1.lock(); m2.lock();
+ {
+ LG lg(m1, m2, std::adopt_lock);
+ assert(m1.locked && m2.locked);
+ }
+ assert(!m1.locked && !m2.locked);
+ }
+ {
+ TestMutex m1, m2, m3;
+ using LG = std::lock_guard<TestMutex, TestMutex, TestMutex>;
+ m1.lock(); m2.lock(); m3.lock();
+ {
+ LG lg(m1, m2, m3, std::adopt_lock);
+ assert(m1.locked && m2.locked && m3.locked);
+ }
+ assert(!m1.locked && !m2.locked && !m3.locked);
+ }
+
+}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_assign.fail.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_assign.fail.cpp
new file mode 100644
index 0000000000000..18193e000edc7
--- /dev/null
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_assign.fail.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: c++98, c++03
+
+// <mutex>
+
+// template <class ...Mutex> class lock_guard;
+
+// lock_guard& operator=(lock_guard const&) = delete;
+
+#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
+#include <mutex>
+
+int main()
+{
+ using M = std::mutex;
+ M m0, m1, m2;
+ M om0, om1, om2;
+ {
+ using LG = std::lock_guard<>;
+ LG lg1, lg2;
+ lg1 = lg2; // expected-error{{overload resolution selected deleted operator '='}}
+ }
+ {
+ using LG = std::lock_guard<M, M>;
+ LG lg1(m0, m1);
+ LG lg2(om0, om1);
+ lg1 = lg2; // expected-error{{overload resolution selected deleted operator '='}}
+ }
+ {
+ using LG = std::lock_guard<M, M, M>;
+ LG lg1(m0, m1, m2);
+ LG lg2(om0, om1, om2);
+ lg1 = lg2; // expected-error{{overload resolution selected deleted operator '='}}
+ }
+}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_copy.fail.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_copy.fail.cpp
new file mode 100644
index 0000000000000..6dc37e970fb60
--- /dev/null
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_copy.fail.cpp
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: c++98, c++03
+
+// <mutex>
+
+// template <class ...Mutex> class lock_guard;
+
+// lock_guard(lock_guard const&) = delete;
+
+#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
+#include <mutex>
+
+int main()
+{
+ using M = std::mutex;
+ M m0, m1, m2;
+ {
+ using LG = std::lock_guard<>;
+ const LG Orig;
+ LG Copy(Orig); // expected-error{{call to deleted constructor of 'LG'}}
+ }
+ {
+ using LG = std::lock_guard<M, M>;
+ const LG Orig(m0, m1);
+ LG Copy(Orig); // expected-error{{call to deleted constructor of 'LG'}}
+ }
+ {
+ using LG = std::lock_guard<M, M, M>;
+ const LG Orig(m0, m1, m2);
+ LG Copy(Orig); // expected-error{{call to deleted constructor of 'LG'}}
+ }
+}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex.fail.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex.fail.cpp
new file mode 100644
index 0000000000000..866538a2834f5
--- /dev/null
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex.fail.cpp
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: c++98, c++03
+
+// <mutex>
+
+// template <class ...Mutex> class lock_guard;
+
+// explicit lock_guard(Mutex&...);
+
+#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
+#include <mutex>
+
+template <class LG>
+void test_conversion(LG) {}
+
+int main()
+{
+ using M = std::mutex;
+ M m0, m1, m2;
+ M n0, n1, n2;
+ {
+ using LG = std::lock_guard<>;
+ LG lg = {}; // expected-error{{chosen constructor is explicit in copy-initialization}}
+ test_conversion<LG>({}); // expected-error{{no matching function for call}}
+ ((void)lg);
+ }
+ {
+ using LG = std::lock_guard<M, M>;
+ LG lg = {m0, m1}; // expected-error{{chosen constructor is explicit in copy-initialization}}
+ test_conversion<LG>({n0, n1}); // expected-error{{no matching function for call}}
+ ((void)lg);
+ }
+ {
+ using LG = std::lock_guard<M, M, M>;
+ LG lg = {m0, m1, m2}; // expected-error{{chosen constructor is explicit in copy-initialization}}
+ test_conversion<LG>({n0, n1, n2}); // expected-error{{no matching function for call}}
+ }
+}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex.pass.cpp
new file mode 100644
index 0000000000000..4910d837cae32
--- /dev/null
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex.pass.cpp
@@ -0,0 +1,115 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: c++98, c++03
+
+// <mutex>
+
+// template <class ...Mutex> class lock_guard;
+
+// explicit lock_guard(mutex_type& m);
+
+#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
+#include <mutex>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct TestMutex {
+ bool locked = false;
+ TestMutex() = default;
+ ~TestMutex() { assert(!locked); }
+
+ void lock() { assert(!locked); locked = true; }
+ bool try_lock() { if (locked) return false; locked = true; return true; }
+ void unlock() { assert(locked); locked = false; }
+
+ TestMutex(TestMutex const&) = delete;
+ TestMutex& operator=(TestMutex const&) = delete;
+};
+
+#if !defined(TEST_HAS_NO_EXCEPTIONS)
+struct TestMutexThrows {
+ bool locked = false;
+ bool throws_on_lock = false;
+
+ TestMutexThrows() = default;
+ ~TestMutexThrows() { assert(!locked); }
+
+ void lock() {
+ assert(!locked);
+ if (throws_on_lock) {
+ throw 42;
+ }
+ locked = true;
+ }
+
+ bool try_lock() {
+ if (locked) return false;
+ lock();
+ return true;
+ }
+
+ void unlock() { assert(locked); locked = false; }
+
+ TestMutexThrows(TestMutexThrows const&) = delete;
+ TestMutexThrows& operator=(TestMutexThrows const&) = delete;
+};
+#endif // !defined(TEST_HAS_NO_EXCEPTIONS)
+
+int main()
+{
+ {
+ using LG = std::lock_guard<>;
+ LG lg;
+ }
+ {
+ using LG = std::lock_guard<TestMutex, TestMutex>;
+ TestMutex m1, m2;
+ {
+ LG lg(m1, m2);
+ assert(m1.locked && m2.locked);
+ }
+ assert(!m1.locked && !m2.locked);
+ }
+ {
+ using LG = std::lock_guard<TestMutex, TestMutex, TestMutex>;
+ TestMutex m1, m2, m3;
+ {
+ LG lg(m1, m2, m3);
+ assert(m1.locked && m2.locked && m3.locked);
+ }
+ assert(!m1.locked && !m2.locked && !m3.locked);
+ }
+#if !defined(TEST_HAS_NO_EXCEPTIONS)
+ {
+ using MT = TestMutexThrows;
+ using LG = std::lock_guard<MT, MT>;
+ MT m1, m2;
+ m1.throws_on_lock = true;
+ try {
+ LG lg(m1, m2);
+ assert(false);
+ } catch (int) {}
+ assert(!m1.locked && !m2.locked);
+ }
+ {
+ using MT = TestMutexThrows;
+ using LG = std::lock_guard<MT, MT, MT>;
+ MT m1, m2, m3;
+ m2.throws_on_lock = true;
+ try {
+ LG lg(m1, m2, m3);
+ assert(false);
+ } catch (int) {}
+ assert(!m1.locked && !m2.locked && !m3.locked);
+ }
+#endif
+}
diff --git a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.recursive/native_handle.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex_cxx03.pass.cpp
index 10626bc4072e0..3c134e0b88615 100644
--- a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.recursive/native_handle.pass.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex_cxx03.pass.cpp
@@ -11,17 +11,11 @@
// <mutex>
-// class recursive_mutex;
+// template <class ...Mutex> class lock_guard;
-// typedef pthread_mutex_t* native_handle_type;
-// native_handle_type native_handle();
+// Test that the variadic lock guard implementation compiles in all standard
+// dialects, including C++03, even though it is forward declared using
+// variadic templates.
-#include <mutex>
-#include <cassert>
-
-int main()
-{
- std::recursive_mutex m;
- pthread_mutex_t* h = m.native_handle();
- assert(h);
-}
+#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
+#include "mutex.pass.cpp" // Use the existing non-variadic test
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_types.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_types.pass.cpp
new file mode 100644
index 0000000000000..2b06742a673e6
--- /dev/null
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_types.pass.cpp
@@ -0,0 +1,78 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: c++98, c++03
+
+// <mutex>
+
+// template <class Mutex>
+// class lock_guard
+// {
+// public:
+// typedef Mutex mutex_type;
+// ...
+// };
+
+#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
+#include <mutex>
+#include <type_traits>
+
+struct NAT {};
+
+template <class LG>
+auto test_typedef(int) -> typename LG::mutex_type;
+
+template <class LG>
+auto test_typedef(...) -> NAT;
+
+template <class LG>
+constexpr bool has_mutex_type() {
+ return !std::is_same<decltype(test_typedef<LG>(0)), NAT>::value;
+}
+
+int main()
+{
+ {
+ using T = std::lock_guard<>;
+ static_assert(!has_mutex_type<T>(), "");
+ }
+ {
+ using M1 = std::mutex;
+ using T = std::lock_guard<M1>;
+ static_assert(std::is_same<T::mutex_type, M1>::value, "");
+ }
+ {
+ using M1 = std::recursive_mutex;
+ using T = std::lock_guard<M1>;
+ static_assert(std::is_same<T::mutex_type, M1>::value, "");
+ }
+ {
+ using M1 = std::mutex;
+ using M2 = std::recursive_mutex;
+ using T = std::lock_guard<M1, M2>;
+ static_assert(!has_mutex_type<T>(), "");
+ }
+ {
+ using M1 = std::mutex;
+ using M2 = std::recursive_mutex;
+ using T = std::lock_guard<M1, M1, M2>;
+ static_assert(!has_mutex_type<T>(), "");
+ }
+ {
+ using M1 = std::mutex;
+ using T = std::lock_guard<M1, M1>;
+ static_assert(!has_mutex_type<T>(), "");
+ }
+ {
+ using M1 = std::recursive_mutex;
+ using T = std::lock_guard<M1, M1, M1>;
+ static_assert(!has_mutex_type<T>(), "");
+ }
+}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/copy_assign.fail.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/copy_assign.fail.cpp
index 446807f3f3335..79f43e860ca2f 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/copy_assign.fail.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/copy_assign.fail.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11
// <shared_mutex>
// template <class Mutex> class shared_lock;
@@ -15,20 +16,12 @@
#include <shared_mutex>
-#if _LIBCPP_STD_VER > 11
-
std::shared_timed_mutex m0;
std::shared_timed_mutex m1;
-#endif // _LIBCPP_STD_VER > 11
-
int main()
{
-#if _LIBCPP_STD_VER > 11
std::shared_lock<std::shared_timed_mutex> lk0(m0);
std::shared_lock<std::shared_timed_mutex> lk1(m1);
lk1 = lk0;
-#else
-# error
-#endif // _LIBCPP_STD_VER > 11
}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/copy_ctor.fail.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/copy_ctor.fail.cpp
index 370c1fa4e3361..d6bf57947afe0 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/copy_ctor.fail.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/copy_ctor.fail.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11
// <shared_mutex>
// template <class Mutex> class shared_lock;
@@ -15,16 +16,10 @@
#include <shared_mutex>
-#if _LIBCPP_STD_VER > 11
std::shared_timed_mutex m;
-#endif // _LIBCPP_STD_VER > 11
int main()
{
-#if _LIBCPP_STD_VER > 11
std::shared_lock<std::shared_timed_mutex> lk0(m);
std::shared_lock<std::shared_timed_mutex> lk = lk0;
-#else
-# error
-#endif // _LIBCPP_STD_VER > 11
}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp
index 15c193c60b5d3..bd707bb90ce10 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp
@@ -18,17 +18,33 @@
#include <shared_mutex>
#include <cassert>
+#include "nasty_containers.hpp"
-std::shared_timed_mutex m0;
-std::shared_timed_mutex m1;
int main()
{
- std::shared_lock<std::shared_timed_mutex> lk0(m0);
- std::shared_lock<std::shared_timed_mutex> lk1(m1);
+ {
+ typedef std::shared_timed_mutex M;
+ M m0;
+ M m1;
+ std::shared_lock<M> lk0(m0);
+ std::shared_lock<M> lk1(m1);
lk1 = std::move(lk0);
- assert(lk1.mutex() == &m0);
+ assert(lk1.mutex() == std::addressof(m0));
assert(lk1.owns_lock() == true);
assert(lk0.mutex() == nullptr);
assert(lk0.owns_lock() == false);
+ }
+ {
+ typedef nasty_mutex M;
+ M m0;
+ M m1;
+ std::shared_lock<M> lk0(m0);
+ std::shared_lock<M> lk1(m1);
+ lk1 = std::move(lk0);
+ assert(lk1.mutex() == std::addressof(m0));
+ assert(lk1.owns_lock() == true);
+ assert(lk0.mutex() == nullptr);
+ assert(lk0.owns_lock() == false);
+ }
}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_ctor.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_ctor.pass.cpp
index 4f4f6a5e9fbdb..c29a3fb04d0ff 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_ctor.pass.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_ctor.pass.cpp
@@ -18,14 +18,28 @@
#include <shared_mutex>
#include <cassert>
+#include "nasty_containers.hpp"
int main()
{
- std::shared_timed_mutex m;
- std::shared_lock<std::shared_timed_mutex> lk0(m);
- std::shared_lock<std::shared_timed_mutex> lk = std::move(lk0);
- assert(lk.mutex() == &m);
+ {
+ typedef std::shared_timed_mutex M;
+ M m;
+ std::shared_lock<M> lk0(m);
+ std::shared_lock<M> lk = std::move(lk0);
+ assert(lk.mutex() == std::addressof(m));
assert(lk.owns_lock() == true);
assert(lk0.mutex() == nullptr);
assert(lk0.owns_lock() == false);
+ }
+ {
+ typedef nasty_mutex M;
+ M m;
+ std::shared_lock<M> lk0(m);
+ std::shared_lock<M> lk = std::move(lk0);
+ assert(lk.mutex() == std::addressof(m));
+ assert(lk.owns_lock() == true);
+ assert(lk0.mutex() == nullptr);
+ assert(lk0.owns_lock() == false);
+ }
}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp
index 995210221065e..341f0ce7efd2c 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp
@@ -18,12 +18,24 @@
#include <shared_mutex>
#include <cassert>
+#include "nasty_containers.hpp"
int main()
{
- std::shared_timed_mutex m;
- m.lock_shared();
- std::shared_lock<std::shared_timed_mutex> lk(m, std::adopt_lock);
- assert(lk.mutex() == &m);
+ {
+ typedef std::shared_timed_mutex M;
+ M m;
+ m.lock();
+ std::unique_lock<M> lk(m, std::adopt_lock);
+ assert(lk.mutex() == std::addressof(m));
assert(lk.owns_lock() == true);
+ }
+ {
+ typedef nasty_mutex M;
+ M m;
+ m.lock();
+ std::unique_lock<M> lk(m, std::adopt_lock);
+ assert(lk.mutex() == std::addressof(m));
+ assert(lk.owns_lock() == true);
+ }
}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp
index d81796b95bf3c..5fbb7244ef8ef 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp
@@ -18,11 +18,22 @@
#include <shared_mutex>
#include <cassert>
+#include "nasty_containers.hpp"
int main()
{
- std::shared_timed_mutex m;
- std::shared_lock<std::shared_timed_mutex> lk(m, std::defer_lock);
- assert(lk.mutex() == &m);
+ {
+ typedef std::shared_timed_mutex M;
+ M m;
+ std::unique_lock<M> lk(m, std::defer_lock);
+ assert(lk.mutex() == std::addressof(m));
assert(lk.owns_lock() == false);
+ }
+ {
+ typedef nasty_mutex M;
+ M m;
+ std::unique_lock<M> lk(m, std::defer_lock);
+ assert(lk.mutex() == std::addressof(m));
+ assert(lk.owns_lock() == false);
+ }
}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.fail.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.fail.cpp
index 4f477449d6a28..8d864ea8e7da6 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.fail.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.fail.cpp
@@ -16,16 +16,18 @@
#include <mutex>
#include <cassert>
-std::mutex m0;
-std::mutex m1;
-
int main()
{
- std::unique_lock<std::mutex> lk0(m0);
- std::unique_lock<std::mutex> lk1(m1);
+ {
+ typedef std::mutex M;
+ M m0;
+ M m1;
+ std::unique_lock<M> lk0(m0);
+ std::unique_lock<M> lk1(m1);
lk1 = lk0;
assert(lk1.mutex() == &m0);
assert(lk1.owns_lock() == true);
assert(lk0.mutex() == nullptr);
assert(lk0.owns_lock() == false);
+ }
}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.fail.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.fail.cpp
index 4888fe90d92c6..067302127cadf 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.fail.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.fail.cpp
@@ -16,14 +16,16 @@
#include <mutex>
#include <cassert>
-std::mutex m;
-
int main()
{
- std::unique_lock<std::mutex> lk0(m);
- std::unique_lock<std::mutex> lk = lk0;
+ {
+ typedef std::mutex M;
+ M m;
+ std::unique_lock<M> lk0(m);
+ std::unique_lock<M> lk = lk0;
assert(lk.mutex() == &m);
assert(lk.owns_lock() == true);
assert(lk0.mutex() == nullptr);
assert(lk0.owns_lock() == false);
+ }
}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp
index 4dff853088ac7..e5db685e46e75 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp
@@ -17,19 +17,34 @@
#include <mutex>
#include <cassert>
-
-std::mutex m0;
-std::mutex m1;
+#include "nasty_containers.hpp"
int main()
{
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
- std::unique_lock<std::mutex> lk0(m0);
- std::unique_lock<std::mutex> lk1(m1);
+ {
+ typedef std::mutex M;
+ M m0;
+ M m1;
+ std::unique_lock<M> lk0(m0);
+ std::unique_lock<M> lk1(m1);
+ lk1 = std::move(lk0);
+ assert(lk1.mutex() == std::addressof(m0));
+ assert(lk1.owns_lock() == true);
+ assert(lk0.mutex() == nullptr);
+ assert(lk0.owns_lock() == false);
+ }
+ {
+ typedef nasty_mutex M;
+ M m0;
+ M m1;
+ std::unique_lock<M> lk0(m0);
+ std::unique_lock<M> lk1(m1);
lk1 = std::move(lk0);
- assert(lk1.mutex() == &m0);
+ assert(lk1.mutex() == std::addressof(m0));
assert(lk1.owns_lock() == true);
assert(lk0.mutex() == nullptr);
assert(lk0.owns_lock() == false);
+ }
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp
index aa640ee6d746f..427deabc5a59d 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp
@@ -17,17 +17,30 @@
#include <mutex>
#include <cassert>
-
-std::mutex m;
+#include "nasty_containers.hpp"
int main()
{
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
- std::unique_lock<std::mutex> lk0(m);
- std::unique_lock<std::mutex> lk = std::move(lk0);
- assert(lk.mutex() == &m);
+ {
+ typedef std::mutex M;
+ M m;
+ std::unique_lock<M> lk0(m);
+ std::unique_lock<M> lk = std::move(lk0);
+ assert(lk.mutex() == std::addressof(m));
+ assert(lk.owns_lock() == true);
+ assert(lk0.mutex() == nullptr);
+ assert(lk0.owns_lock() == false);
+ }
+ {
+ typedef nasty_mutex M;
+ M m;
+ std::unique_lock<M> lk0(m);
+ std::unique_lock<M> lk = std::move(lk0);
+ assert(lk.mutex() == std::addressof(m));
assert(lk.owns_lock() == true);
assert(lk0.mutex() == nullptr);
assert(lk0.owns_lock() == false);
+ }
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp
index 9c3a7b6505a46..20f7d249b6f49 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp
@@ -17,12 +17,24 @@
#include <mutex>
#include <cassert>
+#include "nasty_containers.hpp"
int main()
{
- std::mutex m;
+ {
+ typedef std::mutex M;
+ M m;
m.lock();
- std::unique_lock<std::mutex> lk(m, std::adopt_lock);
- assert(lk.mutex() == &m);
+ std::unique_lock<M> lk(m, std::adopt_lock);
+ assert(lk.mutex() == std::addressof(m));
assert(lk.owns_lock() == true);
+ }
+ {
+ typedef nasty_mutex M;
+ M m;
+ m.lock();
+ std::unique_lock<M> lk(m, std::adopt_lock);
+ assert(lk.mutex() == std::addressof(m));
+ assert(lk.owns_lock() == true);
+ }
}
diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp
index bf622311f0132..242dacb1eb922 100644
--- a/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp
+++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp
@@ -17,11 +17,22 @@
#include <mutex>
#include <cassert>
+#include "nasty_containers.hpp"
int main()
{
- std::mutex m;
- std::unique_lock<std::mutex> lk(m, std::defer_lock);
- assert(lk.mutex() == &m);
+ {
+ typedef std::mutex M;
+ M m;
+ std::unique_lock<M> lk(m, std::defer_lock);
+ assert(lk.mutex() == std::addressof(m));
assert(lk.owns_lock() == false);
+ }
+ {
+ typedef nasty_mutex M;
+ M m;
+ std::unique_lock<M> lk(m, std::defer_lock);
+ assert(lk.mutex() == std::addressof(m));
+ assert(lk.owns_lock() == false);
+ }
}
diff --git a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.pass.cpp b/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.pass.cpp
deleted file mode 100644
index 12c80f02c340d..0000000000000
--- a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.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
-
-// <mutex>
-
-// class mutex;
-
-// typedef pthread_mutex_t* native_handle_type;
-// native_handle_type native_handle();
-
-#include <mutex>
-#include <cassert>
-
-int main()
-{
- std::mutex m;
- pthread_mutex_t* h = m.native_handle();
- assert(h);
-}
diff --git a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.shared_mutex.requirements/thread.shared_mutex.class/assign.fail.cpp b/test/std/thread/thread.mutex/thread.mutex.requirements/thread.shared_mutex.requirements/thread.shared_mutex.class/assign.fail.cpp
index 5c67a34ab52bb..81995f6c88883 100644
--- a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.shared_mutex.requirements/thread.shared_mutex.class/assign.fail.cpp
+++ b/test/std/thread/thread.mutex/thread.mutex.requirements/thread.shared_mutex.requirements/thread.shared_mutex.class/assign.fail.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
+// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <shared_mutex>
diff --git a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.shared_mutex.requirements/thread.shared_mutex.class/copy.fail.cpp b/test/std/thread/thread.mutex/thread.mutex.requirements/thread.shared_mutex.requirements/thread.shared_mutex.class/copy.fail.cpp
index c7cac6041c824..e4bee4bb7ad13 100644
--- a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.shared_mutex.requirements/thread.shared_mutex.class/copy.fail.cpp
+++ b/test/std/thread/thread.mutex/thread.mutex.requirements/thread.shared_mutex.requirements/thread.shared_mutex.class/copy.fail.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
+// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <shared_mutex>
diff --git a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.sharedtimedmutex.requirements/thread.sharedtimedmutex.class/assign.fail.cpp b/test/std/thread/thread.mutex/thread.mutex.requirements/thread.sharedtimedmutex.requirements/thread.sharedtimedmutex.class/assign.fail.cpp
index 528aaca6d9e14..0c5bfa804bea2 100644
--- a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.sharedtimedmutex.requirements/thread.sharedtimedmutex.class/assign.fail.cpp
+++ b/test/std/thread/thread.mutex/thread.mutex.requirements/thread.sharedtimedmutex.requirements/thread.sharedtimedmutex.class/assign.fail.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11
// <shared_mutex>
// class shared_timed_mutex;
@@ -17,11 +18,7 @@
int main()
{
-#if _LIBCPP_STD_VER > 11
std::shared_timed_mutex m0;
std::shared_timed_mutex m1;
m1 = m0;
-#else
-# error
-#endif
}
diff --git a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.sharedtimedmutex.requirements/thread.sharedtimedmutex.class/copy.fail.cpp b/test/std/thread/thread.mutex/thread.mutex.requirements/thread.sharedtimedmutex.requirements/thread.sharedtimedmutex.class/copy.fail.cpp
index dbf01002e6912..3656ec62ec17a 100644
--- a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.sharedtimedmutex.requirements/thread.sharedtimedmutex.class/copy.fail.cpp
+++ b/test/std/thread/thread.mutex/thread.mutex.requirements/thread.sharedtimedmutex.requirements/thread.sharedtimedmutex.class/copy.fail.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11
// <shared_mutex>
// class shared_timed_mutex;
@@ -17,10 +18,6 @@
int main()
{
-#if _LIBCPP_STD_VER > 11
std::shared_timed_mutex m0;
std::shared_timed_mutex m1(m0);
-#else
-# error
-#endif
}
diff --git a/test/std/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp b/test/std/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp
index afc318cc3d7a5..71b054fced886 100644
--- a/test/std/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp
+++ b/test/std/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp
@@ -21,6 +21,8 @@
#include <thread>
#include <cassert>
+#include "test_macros.h"
+
typedef std::chrono::milliseconds ms;
std::once_flag flg0;
@@ -171,7 +173,7 @@ public:
void operator()(int&) {}
};
-#if __cplusplus >= 201103L
+#if TEST_STD_VER >= 11
// reference qualifiers on functions are a C++11 extension
struct RefQual
{
@@ -240,7 +242,7 @@ int main()
int i = 0;
std::call_once(f, NonCopyable(), i);
}
-#if __cplusplus >= 201103L
+#if TEST_STD_VER >= 11
// reference qualifiers on functions are a C++11 extension
{
std::once_flag f1, f2;
diff --git a/test/std/thread/thread.mutex/version.pass.cpp b/test/std/thread/thread.mutex/version.pass.cpp
deleted file mode 100644
index 81b52c79204b8..0000000000000
--- a/test/std/thread/thread.mutex/version.pass.cpp
+++ /dev/null
@@ -1,20 +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.
-//
-//===----------------------------------------------------------------------===//
-
-// <mutex>
-
-#include <mutex>
-
-#ifndef _LIBCPP_VERSION
-#error _LIBCPP_VERSION not defined
-#endif
-
-int main()
-{
-}
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 3de15af8929bf..5dd6a40a0eb7a 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 a331add962635..54fc0b80280c8 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 726395d990440..3dd7c6a6014c6 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 0512e49dcb336..f0c3ef74c9abb 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 c8807a965c44b..0000000000000
--- 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 a5bf77031ccaf..0000000000000
--- 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), "");
-}
diff --git a/test/std/thread/thread.threads/version.pass.cpp b/test/std/thread/thread.threads/version.pass.cpp
deleted file mode 100644
index d16b0eb068428..0000000000000
--- a/test/std/thread/thread.threads/version.pass.cpp
+++ /dev/null
@@ -1,22 +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>
-
-#include <thread>
-
-#ifndef _LIBCPP_VERSION
-#error _LIBCPP_VERSION not defined
-#endif
-
-int main()
-{
-}