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:
@@ -49,7 +49,6 @@
|
|||||||
#define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB
|
#define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB
|
||||||
#define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
|
#define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
|
||||||
#define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
|
#define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
|
||||||
#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
|
|
||||||
// Don't use a nullptr_t simulation type in C++03 instead using C++11 nullptr
|
// Don't use a nullptr_t simulation type in C++03 instead using C++11 nullptr
|
||||||
// provided under the alternate keyword __nullptr, which changes the mangling
|
// provided under the alternate keyword __nullptr, which changes the mangling
|
||||||
// of nullptr_t. This option is ABI incompatible with GCC in C++03 mode.
|
// of nullptr_t. This option is ABI incompatible with GCC in C++03 mode.
|
||||||
@@ -1076,6 +1075,10 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
|
|||||||
# define _LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE
|
# define _LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE
|
||||||
#endif // _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES
|
#endif // _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES
|
||||||
|
|
||||||
|
#if !defined(__cpp_deduction_guides) || __cpp_deduction_guides < 201611
|
||||||
|
# define _LIBCPP_HAS_NO_DEDUCTION_GUIDES
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
#endif // _LIBCPP_CONFIG
|
#endif // _LIBCPP_CONFIG
|
||||||
|
|||||||
@@ -80,21 +80,9 @@ constexpr adopt_lock_t adopt_lock = adopt_lock_t();
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Forward declare lock_guard as a variadic template even in C++03 to keep
|
|
||||||
// the mangling consistent between dialects.
|
|
||||||
#if defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD)
|
|
||||||
template <class ..._Mutexes>
|
|
||||||
class _LIBCPP_TEMPLATE_VIS lock_guard;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <class _Mutex>
|
template <class _Mutex>
|
||||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
|
class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
|
||||||
#if !defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD)
|
|
||||||
lock_guard
|
lock_guard
|
||||||
#else
|
|
||||||
lock_guard<_Mutex>
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef _Mutex mutex_type;
|
typedef _Mutex mutex_type;
|
||||||
|
|||||||
@@ -109,15 +109,17 @@ public:
|
|||||||
lock_guard& operator=(lock_guard const&) = delete;
|
lock_guard& operator=(lock_guard const&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class... MutexTypes> // Variadic lock_guard only provided in ABI V2.
|
template <class... MutexTypes>
|
||||||
class lock_guard
|
class scoped_lock // C++17
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit lock_guard(MutexTypes&... m);
|
using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex
|
||||||
lock_guard(MutexTypes&... m, adopt_lock_t);
|
|
||||||
~lock_guard();
|
explicit scoped_lock(MutexTypes&... m);
|
||||||
lock_guard(lock_guard const&) = delete;
|
scoped_lock(MutexTypes&... m, adopt_lock_t);
|
||||||
lock_guard& operator=(lock_guard const&) = delete;
|
~scoped_lock();
|
||||||
|
scoped_lock(scoped_lock const&) = delete;
|
||||||
|
scoped_lock& operator=(scoped_lock const&) = delete;
|
||||||
private:
|
private:
|
||||||
tuple<MutexTypes&...> pm; // exposition only
|
tuple<MutexTypes&...> pm; // exposition only
|
||||||
};
|
};
|
||||||
@@ -614,50 +616,72 @@ call_once(once_flag& __flag, const _Callable& __func)
|
|||||||
|
|
||||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||||
|
|
||||||
|
#if _LIBCPP_STD_VER > 14
|
||||||
|
template <class ..._Mutexes>
|
||||||
|
class _LIBCPP_TEMPLATE_VIS scoped_lock;
|
||||||
|
|
||||||
#if defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD) \
|
|
||||||
&& !defined(_LIBCPP_CXX03_LANG)
|
|
||||||
template <>
|
template <>
|
||||||
class _LIBCPP_TEMPLATE_VIS lock_guard<> {
|
class _LIBCPP_TEMPLATE_VIS scoped_lock<> {
|
||||||
public:
|
public:
|
||||||
explicit lock_guard() {}
|
explicit scoped_lock() {}
|
||||||
~lock_guard() = default;
|
~scoped_lock() = default;
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
explicit lock_guard(adopt_lock_t) {}
|
explicit scoped_lock(adopt_lock_t) {}
|
||||||
|
|
||||||
lock_guard(lock_guard const&) = delete;
|
scoped_lock(scoped_lock const&) = delete;
|
||||||
lock_guard& operator=(lock_guard const&) = delete;
|
scoped_lock& operator=(scoped_lock const&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class _Mutex>
|
||||||
|
class _LIBCPP_TEMPLATE_VIS scoped_lock<_Mutex> {
|
||||||
|
public:
|
||||||
|
typedef _Mutex mutex_type;
|
||||||
|
private:
|
||||||
|
mutex_type& __m_;
|
||||||
|
public:
|
||||||
|
explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
|
||||||
|
: __m_(__m) {__m_.lock();}
|
||||||
|
|
||||||
|
~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
explicit scoped_lock(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
|
||||||
|
: __m_(__m) {}
|
||||||
|
|
||||||
|
|
||||||
|
scoped_lock(scoped_lock const&) = delete;
|
||||||
|
scoped_lock& operator=(scoped_lock const&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class ..._MArgs>
|
template <class ..._MArgs>
|
||||||
class _LIBCPP_TEMPLATE_VIS lock_guard
|
class _LIBCPP_TEMPLATE_VIS scoped_lock
|
||||||
{
|
{
|
||||||
static_assert(sizeof...(_MArgs) >= 2, "At least 2 lock types required");
|
static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required");
|
||||||
typedef tuple<_MArgs&...> _MutexTuple;
|
typedef tuple<_MArgs&...> _MutexTuple;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
explicit lock_guard(_MArgs&... __margs)
|
explicit scoped_lock(_MArgs&... __margs)
|
||||||
: __t_(__margs...)
|
: __t_(__margs...)
|
||||||
{
|
{
|
||||||
_VSTD::lock(__margs...);
|
_VSTD::lock(__margs...);
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
lock_guard(_MArgs&... __margs, adopt_lock_t)
|
scoped_lock(_MArgs&... __margs, adopt_lock_t)
|
||||||
: __t_(__margs...)
|
: __t_(__margs...)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
~lock_guard() {
|
~scoped_lock() {
|
||||||
typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
|
typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
|
||||||
__unlock_unpack(_Indices{}, __t_);
|
__unlock_unpack(_Indices{}, __t_);
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_guard(lock_guard const&) = delete;
|
scoped_lock(scoped_lock const&) = delete;
|
||||||
lock_guard& operator=(lock_guard const&) = delete;
|
scoped_lock& operator=(scoped_lock const&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <size_t ..._Indx>
|
template <size_t ..._Indx>
|
||||||
@@ -669,7 +693,7 @@ private:
|
|||||||
_MutexTuple __t_;
|
_MutexTuple __t_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _LIBCPP_ABI_VARIADIC_LOCK_GUARD
|
#endif // _LIBCPP_STD_VER > 14
|
||||||
|
|
||||||
_LIBCPP_END_NAMESPACE_STD
|
_LIBCPP_END_NAMESPACE_STD
|
||||||
|
|
||||||
|
|||||||
@@ -1,37 +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
|
|
||||||
|
|
||||||
// TODO(EricWF) Investigate why typeid(...).name() returns a different string
|
|
||||||
// on GCC 4.9 but not newer GCCs.
|
|
||||||
// XFAIL: gcc-4.9
|
|
||||||
// XFAIL: windows
|
|
||||||
|
|
||||||
// THIS TESTS C++03 EXTENSIONS.
|
|
||||||
|
|
||||||
// <mutex>
|
|
||||||
|
|
||||||
// template <class ...Mutex> class lock_guard;
|
|
||||||
|
|
||||||
// Test that the the variadic lock guard implementation mangles the same in
|
|
||||||
// C++11 and C++03. This is important since the mangling of `lock_guard` depends
|
|
||||||
// on it being declared as a variadic template, even in C++03.
|
|
||||||
|
|
||||||
// MODULES_DEFINES: _LIBCPP_ABI_VARIADIC_LOCK_GUARD
|
|
||||||
#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
|
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
|
||||||
#include <typeinfo>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
const std::string expect = "NSt3__110lock_guardIJNS_5mutexEEEE";
|
|
||||||
assert(typeid(std::lock_guard<std::mutex>).name() == expect);
|
|
||||||
}
|
|
||||||
@@ -15,11 +15,16 @@
|
|||||||
|
|
||||||
// explicit lock_guard(mutex_type& m);
|
// explicit lock_guard(mutex_type& m);
|
||||||
|
|
||||||
|
// template<class _Mutex> lock_guard(lock_guard<_Mutex>)
|
||||||
|
// -> lock_guard<_Mutex>; // C++17
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
std::mutex m;
|
std::mutex m;
|
||||||
|
|
||||||
typedef std::chrono::system_clock Clock;
|
typedef std::chrono::system_clock Clock;
|
||||||
@@ -47,4 +52,9 @@ int main()
|
|||||||
std::this_thread::sleep_for(ms(250));
|
std::this_thread::sleep_for(ms(250));
|
||||||
m.unlock();
|
m.unlock();
|
||||||
t.join();
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -8,18 +8,17 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// UNSUPPORTED: libcpp-has-no-threads
|
// UNSUPPORTED: libcpp-has-no-threads
|
||||||
// UNSUPPORTED: c++98, c++03
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
// <mutex>
|
// <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 <mutex>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
struct TestMutex {
|
struct TestMutex {
|
||||||
bool locked = false;
|
bool locked = false;
|
||||||
@@ -36,12 +35,22 @@ struct TestMutex {
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
using LG = std::lock_guard<>;
|
using LG = std::scoped_lock<>;
|
||||||
LG lg(std::adopt_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;
|
TestMutex m1, m2;
|
||||||
using LG = std::lock_guard<TestMutex, TestMutex>;
|
using LG = std::scoped_lock<TestMutex, TestMutex>;
|
||||||
m1.lock(); m2.lock();
|
m1.lock(); m2.lock();
|
||||||
{
|
{
|
||||||
LG lg(m1, m2, std::adopt_lock);
|
LG lg(m1, m2, std::adopt_lock);
|
||||||
@@ -51,7 +60,7 @@ int main()
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
TestMutex m1, m2, m3;
|
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();
|
m1.lock(); m2.lock(); m3.lock();
|
||||||
{
|
{
|
||||||
LG lg(m1, m2, m3, std::adopt_lock);
|
LG lg(m1, m2, m3, std::adopt_lock);
|
||||||
@@ -8,17 +8,16 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// UNSUPPORTED: libcpp-has-no-threads
|
// UNSUPPORTED: libcpp-has-no-threads
|
||||||
// UNSUPPORTED: c++98, c++03
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
// <mutex>
|
// <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 <mutex>
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@@ -26,18 +25,24 @@ int main()
|
|||||||
M m0, m1, m2;
|
M m0, m1, m2;
|
||||||
M om0, om1, om2;
|
M om0, om1, om2;
|
||||||
{
|
{
|
||||||
using LG = std::lock_guard<>;
|
using LG = std::scoped_lock<>;
|
||||||
LG lg1, lg2;
|
LG lg1, lg2;
|
||||||
lg1 = lg2; // expected-error{{overload resolution selected deleted operator '='}}
|
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 lg1(m0, m1);
|
||||||
LG lg2(om0, om1);
|
LG lg2(om0, om1);
|
||||||
lg1 = lg2; // expected-error{{overload resolution selected deleted operator '='}}
|
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 lg1(m0, m1, m2);
|
||||||
LG lg2(om0, om1, om2);
|
LG lg2(om0, om1, om2);
|
||||||
lg1 = lg2; // expected-error{{overload resolution selected deleted operator '='}}
|
lg1 = lg2; // expected-error{{overload resolution selected deleted operator '='}}
|
||||||
@@ -8,34 +8,38 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// UNSUPPORTED: libcpp-has-no-threads
|
// UNSUPPORTED: libcpp-has-no-threads
|
||||||
// UNSUPPORTED: c++98, c++03
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
// <mutex>
|
// <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 <mutex>
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
using M = std::mutex;
|
using M = std::mutex;
|
||||||
M m0, m1, m2;
|
M m0, m1, m2;
|
||||||
{
|
{
|
||||||
using LG = std::lock_guard<>;
|
using LG = std::scoped_lock<>;
|
||||||
const LG Orig;
|
const LG Orig;
|
||||||
LG Copy(Orig); // expected-error{{call to deleted constructor of 'LG'}}
|
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);
|
const LG Orig(m0, m1);
|
||||||
LG Copy(Orig); // expected-error{{call to deleted constructor of 'LG'}}
|
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);
|
const LG Orig(m0, m1, m2);
|
||||||
LG Copy(Orig); // expected-error{{call to deleted constructor of 'LG'}}
|
LG Copy(Orig); // expected-error{{call to deleted constructor of 'LG'}}
|
||||||
}
|
}
|
||||||
@@ -8,17 +8,16 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// UNSUPPORTED: libcpp-has-no-threads
|
// UNSUPPORTED: libcpp-has-no-threads
|
||||||
// UNSUPPORTED: c++98, c++03
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
// <mutex>
|
// <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 <mutex>
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
template <class LG>
|
template <class LG>
|
||||||
void test_conversion(LG) {}
|
void test_conversion(LG) {}
|
||||||
@@ -29,19 +28,25 @@ int main()
|
|||||||
M m0, m1, m2;
|
M m0, m1, m2;
|
||||||
M n0, n1, n2;
|
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}}
|
LG lg = {}; // expected-error{{chosen constructor is explicit in copy-initialization}}
|
||||||
test_conversion<LG>({}); // expected-error{{no matching function for call}}
|
test_conversion<LG>({}); // expected-error{{no matching function for call}}
|
||||||
((void)lg);
|
((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}}
|
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}}
|
test_conversion<LG>({n0, n1}); // expected-error{{no matching function for call}}
|
||||||
((void)lg);
|
((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}}
|
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}}
|
test_conversion<LG>({n0, n1, n2}); // expected-error{{no matching function for call}}
|
||||||
}
|
}
|
||||||
@@ -8,19 +8,16 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// UNSUPPORTED: libcpp-has-no-threads
|
// UNSUPPORTED: libcpp-has-no-threads
|
||||||
// UNSUPPORTED: c++98, c++03
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
// <mutex>
|
// <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 <mutex>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
|
||||||
struct TestMutex {
|
struct TestMutex {
|
||||||
@@ -68,11 +65,20 @@ struct TestMutexThrows {
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
using LG = std::lock_guard<>;
|
using LG = std::scoped_lock<>;
|
||||||
LG lg;
|
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;
|
TestMutex m1, m2;
|
||||||
{
|
{
|
||||||
LG lg(m1, m2);
|
LG lg(m1, m2);
|
||||||
@@ -81,7 +87,7 @@ int main()
|
|||||||
assert(!m1.locked && !m2.locked);
|
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;
|
TestMutex m1, m2, m3;
|
||||||
{
|
{
|
||||||
LG lg(m1, m2, m3);
|
LG lg(m1, m2, m3);
|
||||||
@@ -92,7 +98,18 @@ int main()
|
|||||||
#if !defined(TEST_HAS_NO_EXCEPTIONS)
|
#if !defined(TEST_HAS_NO_EXCEPTIONS)
|
||||||
{
|
{
|
||||||
using MT = TestMutexThrows;
|
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;
|
MT m1, m2;
|
||||||
m1.throws_on_lock = true;
|
m1.throws_on_lock = true;
|
||||||
try {
|
try {
|
||||||
@@ -103,7 +120,7 @@ int main()
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
using MT = TestMutexThrows;
|
using MT = TestMutexThrows;
|
||||||
using LG = std::lock_guard<MT, MT, MT>;
|
using LG = std::scoped_lock<MT, MT, MT>;
|
||||||
MT m1, m2, m3;
|
MT m1, m2, m3;
|
||||||
m2.throws_on_lock = true;
|
m2.throws_on_lock = true;
|
||||||
try {
|
try {
|
||||||
@@ -113,4 +130,26 @@ int main()
|
|||||||
assert(!m1.locked && !m2.locked && !m3.locked);
|
assert(!m1.locked && !m2.locked && !m3.locked);
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
||||||
}
|
}
|
||||||
@@ -8,22 +8,21 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// UNSUPPORTED: libcpp-has-no-threads
|
// UNSUPPORTED: libcpp-has-no-threads
|
||||||
// UNSUPPORTED: c++98, c++03
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
// <mutex>
|
// <mutex>
|
||||||
|
|
||||||
// template <class Mutex>
|
// template <class Mutex...>
|
||||||
// class lock_guard
|
// class scoped_lock
|
||||||
// {
|
// {
|
||||||
// public:
|
// 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 <mutex>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
struct NAT {};
|
struct NAT {};
|
||||||
|
|
||||||
@@ -41,39 +40,39 @@ constexpr bool has_mutex_type() {
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
using T = std::lock_guard<>;
|
using T = std::scoped_lock<>;
|
||||||
static_assert(!has_mutex_type<T>(), "");
|
static_assert(!has_mutex_type<T>(), "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using M1 = std::mutex;
|
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, "");
|
static_assert(std::is_same<T::mutex_type, M1>::value, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using M1 = std::recursive_mutex;
|
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, "");
|
static_assert(std::is_same<T::mutex_type, M1>::value, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using M1 = std::mutex;
|
using M1 = std::mutex;
|
||||||
using M2 = std::recursive_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>(), "");
|
static_assert(!has_mutex_type<T>(), "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using M1 = std::mutex;
|
using M1 = std::mutex;
|
||||||
using M2 = std::recursive_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>(), "");
|
static_assert(!has_mutex_type<T>(), "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using M1 = std::mutex;
|
using M1 = std::mutex;
|
||||||
using T = std::lock_guard<M1, M1>;
|
using T = std::scoped_lock<M1, M1>;
|
||||||
static_assert(!has_mutex_type<T>(), "");
|
static_assert(!has_mutex_type<T>(), "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using M1 = std::recursive_mutex;
|
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>(), "");
|
static_assert(!has_mutex_type<T>(), "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
// explicit shared_lock(mutex_type& m);
|
// explicit shared_lock(mutex_type& m);
|
||||||
|
|
||||||
|
// template<class _Mutex> shared_lock(shared_lock<_Mutex>)
|
||||||
|
// -> shared_lock<_Mutex>; // C++17
|
||||||
|
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -92,4 +95,9 @@ int main()
|
|||||||
t.join();
|
t.join();
|
||||||
q.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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,16 @@
|
|||||||
|
|
||||||
// explicit unique_lock(mutex_type& m);
|
// explicit unique_lock(mutex_type& m);
|
||||||
|
|
||||||
|
// template<class _Mutex> unique_lock(unique_lock<_Mutex>)
|
||||||
|
// -> unique_lock<_Mutex>; // C++17
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
std::mutex m;
|
std::mutex m;
|
||||||
|
|
||||||
typedef std::chrono::system_clock Clock;
|
typedef std::chrono::system_clock Clock;
|
||||||
@@ -47,4 +52,9 @@ int main()
|
|||||||
std::this_thread::sleep_for(ms(250));
|
std::this_thread::sleep_for(ms(250));
|
||||||
m.unlock();
|
m.unlock();
|
||||||
t.join();
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0006r0.html">P0006R0</a></td><td>LWG</td><td>Adopt Type Traits Variable Templates for C++17.</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0006r0.html">P0006R0</a></td><td>LWG</td><td>Adopt Type Traits Variable Templates for C++17.</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0092R1.html">P0092R1</a></td><td>LWG</td><td>Polishing <chrono></td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0092R1.html">P0092R1</a></td><td>LWG</td><td>Polishing <chrono></td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0007R1.html">P0007R1</a></td><td>LWG</td><td>Constant View: A proposal for a <tt>std::as_const</tt> helper function template.</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0007R1.html">P0007R1</a></td><td>LWG</td><td>Constant View: A proposal for a <tt>std::as_const</tt> helper function template.</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0156r0.html" >P0156R0</a></td><td>LWG</td><td>Variadic lock_guard(rev 3).</td><td>Kona</td><td>Complete (ABI V2 Only)</td><td>3.9</td></tr>
|
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0156r0.html" >P0156R0</a></td><td>LWG</td><td>Variadic lock_guard(rev 3).</td><td>Kona</td><td><I>Reverted in Kona</I></td><td>3.9</td></tr>
|
||||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0074R0.html">P0074R0</a></td><td>LWG</td><td>Making <tt>std::owner_less</tt> more flexible</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0074R0.html">P0074R0</a></td><td>LWG</td><td>Making <tt>std::owner_less</tt> more flexible</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0013R1.html">P0013R1</a></td><td>LWG</td><td>Logical type traits rev 2</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0013R1.html">P0013R1</a></td><td>LWG</td><td>Logical type traits rev 2</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||||
<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
|
<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
|
||||||
@@ -142,7 +142,7 @@
|
|||||||
<tr><td><a href="http://wg21.link/P0517R0">P0517R0</a></td><td>LWG</td><td>Make future_error Constructible</td><td>Issaquah</td><td>Complete</td><td>4.0</td></tr>
|
<tr><td><a href="http://wg21.link/P0517R0">P0517R0</a></td><td>LWG</td><td>Make future_error Constructible</td><td>Issaquah</td><td>Complete</td><td>4.0</td></tr>
|
||||||
<tr><td><a href="http://wg21.link/P0521R0">P0521R0</a></td><td>LWG</td><td>Proposed Resolution for CA 14 (shared_ptr use_count/unique)</td><td>Issaquah</td><td><i>Nothing to do</i></td><td>n/a</td></tr>
|
<tr><td><a href="http://wg21.link/P0521R0">P0521R0</a></td><td>LWG</td><td>Proposed Resolution for CA 14 (shared_ptr use_count/unique)</td><td>Issaquah</td><td><i>Nothing to do</i></td><td>n/a</td></tr>
|
||||||
<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
|
<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
|
||||||
<tr><td><a href="http://wg21.link/P0156R2">P0156R2</a></td><td>LWG</td><td>Variadic Lock guard</td><td>Kona</td><td></td><td></td></tr>
|
<tr><td><a href="http://wg21.link/P0156R2">P0156R2</a></td><td>LWG</td><td>Variadic Lock guard(rev 5)</td><td>Kona</td><td>Complete</td><td>5.0</td></tr>
|
||||||
<tr><td><a href="http://wg21.link/P0270R3">P0270R3</a></td><td>CWG</td><td>Removing C dependencies from signal handler wording</td><td>Kona</td><td></td><td></td></tr>
|
<tr><td><a href="http://wg21.link/P0270R3">P0270R3</a></td><td>CWG</td><td>Removing C dependencies from signal handler wording</td><td>Kona</td><td></td><td></td></tr>
|
||||||
<tr><td><a href="http://wg21.link/P0298R3">P0298R3</a></td><td>CWG</td><td>A byte type definition</td><td>Kona</td><td></td><td></td></tr>
|
<tr><td><a href="http://wg21.link/P0298R3">P0298R3</a></td><td>CWG</td><td>A byte type definition</td><td>Kona</td><td></td><td></td></tr>
|
||||||
<tr><td><a href="http://wg21.link/P0317R1">P0317R1</a></td><td>LWG</td><td>Directory Entry Caching for Filesystem</td><td>Kona</td><td></td><td></td></tr>
|
<tr><td><a href="http://wg21.link/P0317R1">P0317R1</a></td><td>LWG</td><td>Directory Entry Caching for Filesystem</td><td>Kona</td><td></td><td></td></tr>
|
||||||
@@ -489,7 +489,7 @@
|
|||||||
<!-- <tr><td></td><td></td><td></td><td></td></tr> -->
|
<!-- <tr><td></td><td></td><td></td><td></td></tr> -->
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<p>Last Updated: 6-Mar-2017</p>
|
<p>Last Updated: 23-Mar-2017</p>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user