Implement Pp0156r2: 'Variadic Lock Guard, version 5' Reviewed as https://reviews.llvm.org/D31163.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@298681 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Marshall Clow
2017-03-24 03:40:36 +00:00
parent 50e32f569c
commit 59bcc879ab
16 changed files with 201 additions and 155 deletions

View File

@@ -15,11 +15,16 @@
// explicit lock_guard(mutex_type& m);
// template<class _Mutex> lock_guard(lock_guard<_Mutex>)
// -> lock_guard<_Mutex>; // C++17
#include <mutex>
#include <thread>
#include <cstdlib>
#include <cassert>
#include "test_macros.h"
std::mutex m;
typedef std::chrono::system_clock Clock;
@@ -47,4 +52,9 @@ int main()
std::this_thread::sleep_for(ms(250));
m.unlock();
t.join();
#ifdef __cpp_deduction_guides
std::lock_guard lg(m);
static_assert((std::is_same<decltype(lg), std::lock_guard<decltype(m)>>::value), "" );
#endif
}

View File

@@ -1,21 +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>
// template <class ...Mutex> class lock_guard;
// Test that the variadic lock guard implementation compiles in all standard
// dialects, including C++03, even though it is forward declared using
// variadic templates.
// MODULES_DEFINES: _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#include "mutex.pass.cpp" // Use the existing non-variadic test

View File

@@ -8,18 +8,17 @@
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++98, c++03
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <mutex>
// template <class ...Mutex> class lock_guard;
// template <class ...Mutex> class scoped_lock;
// lock_guard(Mutex&..., adopt_lock_t);
// scoped_lock(Mutex&..., adopt_lock_t);
// MODULES_DEFINES: _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#include <mutex>
#include <cassert>
#include "test_macros.h"
struct TestMutex {
bool locked = false;
@@ -36,12 +35,22 @@ struct TestMutex {
int main()
{
{
using LG = std::lock_guard<>;
using LG = std::scoped_lock<>;
LG lg(std::adopt_lock);
}
{
TestMutex m1;
using LG = std::scoped_lock<TestMutex>;
m1.lock();
{
LG lg(m1, std::adopt_lock);
assert(m1.locked);
}
assert(!m1.locked);
}
{
TestMutex m1, m2;
using LG = std::lock_guard<TestMutex, TestMutex>;
using LG = std::scoped_lock<TestMutex, TestMutex>;
m1.lock(); m2.lock();
{
LG lg(m1, m2, std::adopt_lock);
@@ -51,7 +60,7 @@ int main()
}
{
TestMutex m1, m2, m3;
using LG = std::lock_guard<TestMutex, TestMutex, TestMutex>;
using LG = std::scoped_lock<TestMutex, TestMutex, TestMutex>;
m1.lock(); m2.lock(); m3.lock();
{
LG lg(m1, m2, m3, std::adopt_lock);

View File

@@ -8,17 +8,16 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++98, c++03
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <mutex>
// template <class ...Mutex> class lock_guard;
// template <class ...Mutex> class scoped_lock;
// lock_guard& operator=(lock_guard const&) = delete;
// scoped_lock& operator=(scoped_lock const&) = delete;
// MODULES_DEFINES: _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#include <mutex>
#include "test_macros.h"
int main()
{
@@ -26,18 +25,24 @@ int main()
M m0, m1, m2;
M om0, om1, om2;
{
using LG = std::lock_guard<>;
using LG = std::scoped_lock<>;
LG lg1, lg2;
lg1 = lg2; // expected-error{{overload resolution selected deleted operator '='}}
}
{
using LG = std::lock_guard<M, M>;
using LG = std::scoped_lock<M>;
LG lg1(m0);
LG lg2(om0);
lg1 = lg2; // expected-error{{overload resolution selected deleted operator '='}}
}
{
using LG = std::scoped_lock<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>;
using LG = std::scoped_lock<M, M, M>;
LG lg1(m0, m1, m2);
LG lg2(om0, om1, om2);
lg1 = lg2; // expected-error{{overload resolution selected deleted operator '='}}

View File

@@ -8,34 +8,38 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++98, c++03
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <mutex>
// template <class ...Mutex> class lock_guard;
// template <class ...Mutex> class scoped_lock;
// lock_guard(lock_guard const&) = delete;
// scoped_lock(scoped_lock const&) = delete;
// MODULES_DEFINES: _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#include <mutex>
#include "test_macros.h"
int main()
{
using M = std::mutex;
M m0, m1, m2;
{
using LG = std::lock_guard<>;
using LG = std::scoped_lock<>;
const LG Orig;
LG Copy(Orig); // expected-error{{call to deleted constructor of 'LG'}}
}
{
using LG = std::lock_guard<M, M>;
using LG = std::scoped_lock<M>;
const LG Orig(m0);
LG Copy(Orig); // expected-error{{call to deleted constructor of 'LG'}}
}
{
using LG = std::scoped_lock<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>;
using LG = std::scoped_lock<M, M, M>;
const LG Orig(m0, m1, m2);
LG Copy(Orig); // expected-error{{call to deleted constructor of 'LG'}}
}

View File

@@ -8,17 +8,16 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++98, c++03
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <mutex>
// template <class ...Mutex> class lock_guard;
// template <class ...Mutex> class scoped_lock;
// explicit lock_guard(Mutex&...);
// explicit scoped_lock(Mutex&...);
// MODULES_DEFINES: _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#include <mutex>
#include "test_macros.h"
template <class LG>
void test_conversion(LG) {}
@@ -29,19 +28,25 @@ int main()
M m0, m1, m2;
M n0, n1, n2;
{
using LG = std::lock_guard<>;
using LG = std::scoped_lock<>;
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>;
using LG = std::scoped_lock<M>;
LG lg = {m0}; // expected-error{{chosen constructor is explicit in copy-initialization}}
test_conversion<LG>({n0}); // expected-error{{no matching function for call}}
((void)lg);
}
{
using LG = std::scoped_lock<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>;
using LG = std::scoped_lock<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}}
}

View File

@@ -8,19 +8,16 @@
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++98, c++03
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <mutex>
// template <class ...Mutex> class lock_guard;
// template <class ...Mutex> class scoped_lock;
// explicit lock_guard(mutex_type& m);
// explicit scoped_lock(mutex_type& m);
// MODULES_DEFINES: _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#include <mutex>
#include <cassert>
#include "test_macros.h"
struct TestMutex {
@@ -68,11 +65,20 @@ struct TestMutexThrows {
int main()
{
{
using LG = std::lock_guard<>;
using LG = std::scoped_lock<>;
LG lg;
}
{
using LG = std::lock_guard<TestMutex, TestMutex>;
using LG = std::scoped_lock<TestMutex>;
TestMutex m1;
{
LG lg(m1);
assert(m1.locked);
}
assert(!m1.locked);
}
{
using LG = std::scoped_lock<TestMutex, TestMutex>;
TestMutex m1, m2;
{
LG lg(m1, m2);
@@ -81,7 +87,7 @@ int main()
assert(!m1.locked && !m2.locked);
}
{
using LG = std::lock_guard<TestMutex, TestMutex, TestMutex>;
using LG = std::scoped_lock<TestMutex, TestMutex, TestMutex>;
TestMutex m1, m2, m3;
{
LG lg(m1, m2, m3);
@@ -92,7 +98,18 @@ int main()
#if !defined(TEST_HAS_NO_EXCEPTIONS)
{
using MT = TestMutexThrows;
using LG = std::lock_guard<MT, MT>;
using LG = std::scoped_lock<MT>;
MT m1;
m1.throws_on_lock = true;
try {
LG lg(m1);
assert(false);
} catch (int) {}
assert(!m1.locked);
}
{
using MT = TestMutexThrows;
using LG = std::scoped_lock<MT, MT>;
MT m1, m2;
m1.throws_on_lock = true;
try {
@@ -103,7 +120,7 @@ int main()
}
{
using MT = TestMutexThrows;
using LG = std::lock_guard<MT, MT, MT>;
using LG = std::scoped_lock<MT, MT, MT>;
MT m1, m2, m3;
m2.throws_on_lock = true;
try {
@@ -113,4 +130,26 @@ int main()
assert(!m1.locked && !m2.locked && !m3.locked);
}
#endif
#ifdef __cpp_deduction_guides
{
TestMutex m1, m2, m3;
{
std::scoped_lock sl{};
static_assert((std::is_same<decltype(sl), std::scoped_lock<>>::value), "" );
}
{
std::scoped_lock sl{m1};
static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1)>>::value), "" );
}
{
std::scoped_lock sl{m1, m2};
static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1), decltype(m2)>>::value), "" );
}
{
std::scoped_lock sl{m1, m2, m3};
static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1), decltype(m2), decltype(m3)>>::value), "" );
}
}
#endif
}

View File

@@ -8,22 +8,21 @@
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++98, c++03
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <mutex>
// template <class Mutex>
// class lock_guard
// template <class Mutex...>
// class scoped_lock
// {
// public:
// typedef Mutex mutex_type;
// typedef Mutex mutex_type; // only if sizeof...(Mutex) == 1
// ...
// };
// MODULES_DEFINES: _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
#include <mutex>
#include <type_traits>
#include "test_macros.h"
struct NAT {};
@@ -41,39 +40,39 @@ constexpr bool has_mutex_type() {
int main()
{
{
using T = std::lock_guard<>;
using T = std::scoped_lock<>;
static_assert(!has_mutex_type<T>(), "");
}
{
using M1 = std::mutex;
using T = std::lock_guard<M1>;
using T = std::scoped_lock<M1>;
static_assert(std::is_same<T::mutex_type, M1>::value, "");
}
{
using M1 = std::recursive_mutex;
using T = std::lock_guard<M1>;
using T = std::scoped_lock<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>;
using T = std::scoped_lock<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>;
using T = std::scoped_lock<M1, M1, M2>;
static_assert(!has_mutex_type<T>(), "");
}
{
using M1 = std::mutex;
using T = std::lock_guard<M1, M1>;
using T = std::scoped_lock<M1, M1>;
static_assert(!has_mutex_type<T>(), "");
}
{
using M1 = std::recursive_mutex;
using T = std::lock_guard<M1, M1, M1>;
using T = std::scoped_lock<M1, M1, M1>;
static_assert(!has_mutex_type<T>(), "");
}
}

View File

@@ -18,6 +18,9 @@
// explicit shared_lock(mutex_type& m);
// template<class _Mutex> shared_lock(shared_lock<_Mutex>)
// -> shared_lock<_Mutex>; // C++17
#include <shared_mutex>
#include <thread>
#include <vector>
@@ -92,4 +95,9 @@ int main()
t.join();
q.join();
}
#ifdef __cpp_deduction_guides
std::shared_lock sl(m);
static_assert((std::is_same<decltype(sl), std::shared_lock<decltype(m)>>::value), "" );
#endif
}

View File

@@ -15,11 +15,16 @@
// explicit unique_lock(mutex_type& m);
// template<class _Mutex> unique_lock(unique_lock<_Mutex>)
// -> unique_lock<_Mutex>; // C++17
#include <mutex>
#include <thread>
#include <cstdlib>
#include <cassert>
#include "test_macros.h"
std::mutex m;
typedef std::chrono::system_clock Clock;
@@ -47,4 +52,9 @@ int main()
std::this_thread::sleep_for(ms(250));
m.unlock();
t.join();
#ifdef __cpp_deduction_guides
std::unique_lock ul(m);
static_assert((std::is_same<decltype(ul), std::unique_lock<decltype(m)>>::value), "" );
#endif
}