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
diff --git a/include/__config b/include/__config
index 95ffbe2..9b48a70 100644
--- a/include/__config
+++ b/include/__config
@@ -49,7 +49,6 @@
 #define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB
 #define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
 #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
 // provided under the alternate keyword __nullptr, which changes the mangling
 // of nullptr_t. This option is ABI incompatible with GCC in C++03 mode.
@@ -1076,6 +1075,10 @@
 # define _LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE
 #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 // _LIBCPP_CONFIG
diff --git a/include/__mutex_base b/include/__mutex_base
index f76e966..4940f93 100644
--- a/include/__mutex_base
+++ b/include/__mutex_base
@@ -80,21 +80,9 @@
 
 #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>
 class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
-#if !defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD)
 lock_guard
-#else
-lock_guard<_Mutex>
-#endif
 {
 public:
     typedef _Mutex mutex_type;
diff --git a/include/mutex b/include/mutex
index 11b0f7e..5cc8ca6 100644
--- a/include/mutex
+++ b/include/mutex
@@ -109,15 +109,17 @@
     lock_guard& operator=(lock_guard const&) = delete;
 };
 
-template <class... MutexTypes> // Variadic lock_guard only provided in ABI V2.
-class lock_guard
+template <class... MutexTypes>
+class scoped_lock // C++17
 {
 public:
-    explicit lock_guard(MutexTypes&... m);
-    lock_guard(MutexTypes&... m, adopt_lock_t);
-    ~lock_guard();
-    lock_guard(lock_guard const&) = delete;
-    lock_guard& operator=(lock_guard const&) = delete;
+    using mutex_type = Mutex;  // If MutexTypes... consists of the single type Mutex
+
+    explicit scoped_lock(MutexTypes&... m);
+    scoped_lock(MutexTypes&... m, adopt_lock_t);
+    ~scoped_lock();
+    scoped_lock(scoped_lock const&) = delete;
+    scoped_lock& operator=(scoped_lock const&) = delete;
 private:
     tuple<MutexTypes&...> pm; // exposition only
 };
@@ -614,50 +616,72 @@
 
 #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 <>
-class _LIBCPP_TEMPLATE_VIS lock_guard<> {
+class _LIBCPP_TEMPLATE_VIS scoped_lock<> {
 public:
-    explicit lock_guard() {}
-    ~lock_guard() = default;
+    explicit scoped_lock() {}
+    ~scoped_lock() = default;
 
     _LIBCPP_INLINE_VISIBILITY
-    explicit lock_guard(adopt_lock_t) {}
+    explicit scoped_lock(adopt_lock_t) {}
 
-    lock_guard(lock_guard const&) = delete;
-    lock_guard& operator=(lock_guard const&) = delete;
+    scoped_lock(scoped_lock 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>
-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;
 
 public:
     _LIBCPP_INLINE_VISIBILITY
-    explicit lock_guard(_MArgs&... __margs)
+    explicit scoped_lock(_MArgs&... __margs)
       : __t_(__margs...)
     {
         _VSTD::lock(__margs...);
     }
 
     _LIBCPP_INLINE_VISIBILITY
-    lock_guard(_MArgs&... __margs, adopt_lock_t)
+    scoped_lock(_MArgs&... __margs, adopt_lock_t)
         : __t_(__margs...)
     {
     }
 
     _LIBCPP_INLINE_VISIBILITY
-    ~lock_guard() {
+    ~scoped_lock() {
         typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
         __unlock_unpack(_Indices{}, __t_);
     }
 
-    lock_guard(lock_guard const&) = delete;
-    lock_guard& operator=(lock_guard const&) = delete;
+    scoped_lock(scoped_lock const&) = delete;
+    scoped_lock& operator=(scoped_lock const&) = delete;
 
 private:
     template <size_t ..._Indx>
@@ -669,7 +693,7 @@
     _MutexTuple __t_;
 };
 
-#endif // _LIBCPP_ABI_VARIADIC_LOCK_GUARD
+#endif // _LIBCPP_STD_VER > 14
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/include/shared_mutex b/include/shared_mutex
index 29e8cef..f2fd667 100644
--- a/include/shared_mutex
+++ b/include/shared_mutex
@@ -175,7 +175,7 @@
 #if _LIBCPP_STD_VER > 14
 class _LIBCPP_TYPE_VIS shared_mutex
 {
-	__shared_mutex_base __base;
+    __shared_mutex_base __base;
 public:
     shared_mutex() : __base() {}
     _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default;
@@ -201,7 +201,7 @@
 
 class _LIBCPP_TYPE_VIS shared_timed_mutex
 {
-	__shared_mutex_base __base;
+    __shared_mutex_base __base;
 public:
     shared_timed_mutex();
     _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default;