Move std::unique_lock definition to a separate header
authorJonathan Wakely <jwakely@redhat.com>
Wed, 25 Jul 2018 10:40:12 +0000 (11:40 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Wed, 25 Jul 2018 10:40:12 +0000 (11:40 +0100)
This will allow std::mutex and std::lock_guard to be used elsewhere in
the library without pulling in the whole of <chrono>.

Previously the whole of <bits/std_mutex.h> was conditional on the
_GLIBCXX_USE_C99_STDINT_TR1 macro, but only the std::unique_lock members
that use <chrono> facilities should depend on that. std::mutex only
needs to depend on _GLIBCXX_HAS_GTHREADS and std::lock_guard can be
defined unconditionally.

Some parts of <bits/std_mutex.h> and <mutex> are based on code in
<ext/concurrence.h> which dates from 2003. However, the std::unique_lock
implementation was added in 2008 by r135007, without using any earlier
code. Therefore the new header file has copyright years 2008-2018.

* include/Makefile.am: Add new <bits/unique_lock.h> header.
* include/Makefile.in: Regenerate.
* include/bits/std_mutex.h [!_GLIBCXX_USE_C99_STDINT_TR1] (mutex)
(lock_guard): Define independent of _GLIBCXX_USE_C99_STDINT_TR1.
(unique_lock): Move definition to ...
* include/bits/unique_lock.h: New header.
[!_GLIBCXX_USE_C99_STDINT_TR1] (unique_lock): Define unconditionally.
[_GLIBCXX_USE_C99_STDINT_TR1] (unique_lock(mutex_type&, time_point))
(unique_lock(mutex_type&, duration), unique_lock::try_lock_until)
(unique_lock::try_lock_for): Define only when <chrono> is usable.
* include/std/condition_variable: Include <bits/unique_lock.h>.
* include/std/mutex: Likewise.

From-SVN: r262963

libstdc++-v3/ChangeLog
libstdc++-v3/include/Makefile.am
libstdc++-v3/include/Makefile.in
libstdc++-v3/include/bits/std_mutex.h
libstdc++-v3/include/bits/unique_lock.h [new file with mode: 0644]
libstdc++-v3/include/std/condition_variable
libstdc++-v3/include/std/mutex

index bef5a97cd6ebbab6e07b6ac5a490a007abbc68bc..76903e3e9abf21faca880797b9e87992eaab4427 100644 (file)
@@ -1,3 +1,18 @@
+2018-07-25  Jonathan Wakely  <jwakely@redhat.com>
+
+       * include/Makefile.am: Add new <bits/unique_lock.h> header.
+       * include/Makefile.in: Regenerate.
+       * include/bits/std_mutex.h [!_GLIBCXX_USE_C99_STDINT_TR1] (mutex)
+       (lock_guard): Define independent of _GLIBCXX_USE_C99_STDINT_TR1.
+       (unique_lock): Move definition to ...
+       * include/bits/unique_lock.h: New header.
+       [!_GLIBCXX_USE_C99_STDINT_TR1] (unique_lock): Define unconditionally.
+       [_GLIBCXX_USE_C99_STDINT_TR1] (unique_lock(mutex_type&, time_point))
+       (unique_lock(mutex_type&, duration), unique_lock::try_lock_until)
+       (unique_lock::try_lock_for): Define only when <chrono> is usable.
+       * include/std/condition_variable: Include <bits/unique_lock.h>.
+       * include/std/mutex: Likewise.
+
 2018-07-24  Jonathan Wakely  <jwakely@redhat.com>
 
        * config/abi/pre/gnu.ver: Export new symbols.
index 9daa8856e708f5b3c532808519206235dc3c6ab1..70db3cb6260172d0e1f8d5ce63f5e5bec167d938 100644 (file)
@@ -199,6 +199,7 @@ bits_headers = \
        ${bits_srcdir}/stringfwd.h \
        ${bits_srcdir}/string_view.tcc \
        ${bits_srcdir}/uniform_int_dist.h \
+       ${bits_srcdir}/unique_lock.h \
        ${bits_srcdir}/unique_ptr.h \
        ${bits_srcdir}/unordered_map.h \
        ${bits_srcdir}/unordered_set.h \
index a122c9cfe2cf1c5fa56fa1bdd3d0c82e5b0c2100..0e1cbe489d7b95ffbc01859d5db8481a707189c6 100644 (file)
@@ -492,6 +492,7 @@ bits_headers = \
        ${bits_srcdir}/stringfwd.h \
        ${bits_srcdir}/string_view.tcc \
        ${bits_srcdir}/uniform_int_dist.h \
+       ${bits_srcdir}/unique_lock.h \
        ${bits_srcdir}/unique_ptr.h \
        ${bits_srcdir}/unordered_map.h \
        ${bits_srcdir}/unordered_set.h \
index 34d22907a06ffdf8c075178c1a9b79c55321484b..41a9b30636a7a3d0fbdd046432bdf8dde55f5e9c 100644 (file)
@@ -39,9 +39,6 @@
 #include <system_error>
 #include <bits/functexcept.h>
 #include <bits/gthr.h>
-#include <bits/move.h> // for std::swap
-
-#ifdef _GLIBCXX_USE_C99_STDINT_TR1
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -174,200 +171,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       mutex_type&  _M_device;
     };
 
-  /** @brief A movable scoped lock type.
-   *
-   * A unique_lock controls mutex ownership within a scope. Ownership of the
-   * mutex can be delayed until after construction and can be transferred
-   * to another unique_lock by move construction or move assignment. If a
-   * mutex lock is owned when the destructor runs ownership will be released.
-   */
-  template<typename _Mutex>
-    class unique_lock
-    {
-    public:
-      typedef _Mutex mutex_type;
-
-      unique_lock() noexcept
-      : _M_device(0), _M_owns(false)
-      { }
-
-      explicit unique_lock(mutex_type& __m)
-      : _M_device(std::__addressof(__m)), _M_owns(false)
-      {
-       lock();
-       _M_owns = true;
-      }
-
-      unique_lock(mutex_type& __m, defer_lock_t) noexcept
-      : _M_device(std::__addressof(__m)), _M_owns(false)
-      { }
-
-      unique_lock(mutex_type& __m, try_to_lock_t)
-      : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
-      { }
-
-      unique_lock(mutex_type& __m, adopt_lock_t) noexcept
-      : _M_device(std::__addressof(__m)), _M_owns(true)
-      {
-       // XXX calling thread owns mutex
-      }
-
-      template<typename _Clock, typename _Duration>
-       unique_lock(mutex_type& __m,
-                   const chrono::time_point<_Clock, _Duration>& __atime)
-       : _M_device(std::__addressof(__m)),
-         _M_owns(_M_device->try_lock_until(__atime))
-       { }
-
-      template<typename _Rep, typename _Period>
-       unique_lock(mutex_type& __m,
-                   const chrono::duration<_Rep, _Period>& __rtime)
-       : _M_device(std::__addressof(__m)),
-         _M_owns(_M_device->try_lock_for(__rtime))
-       { }
-
-      ~unique_lock()
-      {
-       if (_M_owns)
-         unlock();
-      }
-
-      unique_lock(const unique_lock&) = delete;
-      unique_lock& operator=(const unique_lock&) = delete;
-
-      unique_lock(unique_lock&& __u) noexcept
-      : _M_device(__u._M_device), _M_owns(__u._M_owns)
-      {
-       __u._M_device = 0;
-       __u._M_owns = false;
-      }
-
-      unique_lock& operator=(unique_lock&& __u) noexcept
-      {
-       if(_M_owns)
-         unlock();
-
-       unique_lock(std::move(__u)).swap(*this);
-
-       __u._M_device = 0;
-       __u._M_owns = false;
-
-       return *this;
-      }
-
-      void
-      lock()
-      {
-       if (!_M_device)
-         __throw_system_error(int(errc::operation_not_permitted));
-       else if (_M_owns)
-         __throw_system_error(int(errc::resource_deadlock_would_occur));
-       else
-         {
-           _M_device->lock();
-           _M_owns = true;
-         }
-      }
-
-      bool
-      try_lock()
-      {
-       if (!_M_device)
-         __throw_system_error(int(errc::operation_not_permitted));
-       else if (_M_owns)
-         __throw_system_error(int(errc::resource_deadlock_would_occur));
-       else
-         {
-           _M_owns = _M_device->try_lock();
-           return _M_owns;
-         }
-      }
-
-      template<typename _Clock, typename _Duration>
-       bool
-       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
-       {
-         if (!_M_device)
-           __throw_system_error(int(errc::operation_not_permitted));
-         else if (_M_owns)
-           __throw_system_error(int(errc::resource_deadlock_would_occur));
-         else
-           {
-             _M_owns = _M_device->try_lock_until(__atime);
-             return _M_owns;
-           }
-       }
-
-      template<typename _Rep, typename _Period>
-       bool
-       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
-       {
-         if (!_M_device)
-           __throw_system_error(int(errc::operation_not_permitted));
-         else if (_M_owns)
-           __throw_system_error(int(errc::resource_deadlock_would_occur));
-         else
-           {
-             _M_owns = _M_device->try_lock_for(__rtime);
-             return _M_owns;
-           }
-        }
-
-      void
-      unlock()
-      {
-       if (!_M_owns)
-         __throw_system_error(int(errc::operation_not_permitted));
-       else if (_M_device)
-         {
-           _M_device->unlock();
-           _M_owns = false;
-         }
-      }
-
-      void
-      swap(unique_lock& __u) noexcept
-      {
-       std::swap(_M_device, __u._M_device);
-       std::swap(_M_owns, __u._M_owns);
-      }
-
-      mutex_type*
-      release() noexcept
-      {
-       mutex_type* __ret = _M_device;
-       _M_device = 0;
-       _M_owns = false;
-       return __ret;
-      }
-
-      bool
-      owns_lock() const noexcept
-      { return _M_owns; }
-
-      explicit operator bool() const noexcept
-      { return owns_lock(); }
-
-      mutex_type*
-      mutex() const noexcept
-      { return _M_device; }
-
-    private:
-      mutex_type*      _M_device;
-      bool             _M_owns; // XXX use atomic_bool
-    };
-
-  /// Swap overload for unique_lock objects.
-  template<typename _Mutex>
-    inline void
-    swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
-    { __x.swap(__y); }
-
   // @} group mutexes
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
-#endif // _GLIBCXX_USE_C99_STDINT_TR1
-
 #endif // C++11
-
 #endif // _GLIBCXX_MUTEX_H
diff --git a/libstdc++-v3/include/bits/unique_lock.h b/libstdc++-v3/include/bits/unique_lock.h
new file mode 100644 (file)
index 0000000..e0e7400
--- /dev/null
@@ -0,0 +1,249 @@
+// std::unique_lock implementation -*- C++ -*-
+
+// Copyright (C) 2008-2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/unique_lock.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{mutex}
+ */
+
+#ifndef _GLIBCXX_UNIQUE_LOCK_H
+#define _GLIBCXX_UNIQUE_LOCK_H 1
+
+#pragma GCC system_header
+
+#if __cplusplus < 201103L
+# include <bits/c++0x_warning.h>
+#else
+
+#include <chrono>
+#include <bits/move.h> // for std::swap
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  /**
+   * @ingroup mutexes
+   * @{
+   */
+
+  /** @brief A movable scoped lock type.
+   *
+   * A unique_lock controls mutex ownership within a scope. Ownership of the
+   * mutex can be delayed until after construction and can be transferred
+   * to another unique_lock by move construction or move assignment. If a
+   * mutex lock is owned when the destructor runs ownership will be released.
+   */
+  template<typename _Mutex>
+    class unique_lock
+    {
+    public:
+      typedef _Mutex mutex_type;
+
+      unique_lock() noexcept
+      : _M_device(0), _M_owns(false)
+      { }
+
+      explicit unique_lock(mutex_type& __m)
+      : _M_device(std::__addressof(__m)), _M_owns(false)
+      {
+       lock();
+       _M_owns = true;
+      }
+
+      unique_lock(mutex_type& __m, defer_lock_t) noexcept
+      : _M_device(std::__addressof(__m)), _M_owns(false)
+      { }
+
+      unique_lock(mutex_type& __m, try_to_lock_t)
+      : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
+      { }
+
+      unique_lock(mutex_type& __m, adopt_lock_t) noexcept
+      : _M_device(std::__addressof(__m)), _M_owns(true)
+      {
+       // XXX calling thread owns mutex
+      }
+
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+      template<typename _Clock, typename _Duration>
+       unique_lock(mutex_type& __m,
+                   const chrono::time_point<_Clock, _Duration>& __atime)
+       : _M_device(std::__addressof(__m)),
+         _M_owns(_M_device->try_lock_until(__atime))
+       { }
+
+      template<typename _Rep, typename _Period>
+       unique_lock(mutex_type& __m,
+                   const chrono::duration<_Rep, _Period>& __rtime)
+       : _M_device(std::__addressof(__m)),
+         _M_owns(_M_device->try_lock_for(__rtime))
+       { }
+#endif
+
+      ~unique_lock()
+      {
+       if (_M_owns)
+         unlock();
+      }
+
+      unique_lock(const unique_lock&) = delete;
+      unique_lock& operator=(const unique_lock&) = delete;
+
+      unique_lock(unique_lock&& __u) noexcept
+      : _M_device(__u._M_device), _M_owns(__u._M_owns)
+      {
+       __u._M_device = 0;
+       __u._M_owns = false;
+      }
+
+      unique_lock& operator=(unique_lock&& __u) noexcept
+      {
+       if(_M_owns)
+         unlock();
+
+       unique_lock(std::move(__u)).swap(*this);
+
+       __u._M_device = 0;
+       __u._M_owns = false;
+
+       return *this;
+      }
+
+      void
+      lock()
+      {
+       if (!_M_device)
+         __throw_system_error(int(errc::operation_not_permitted));
+       else if (_M_owns)
+         __throw_system_error(int(errc::resource_deadlock_would_occur));
+       else
+         {
+           _M_device->lock();
+           _M_owns = true;
+         }
+      }
+
+      bool
+      try_lock()
+      {
+       if (!_M_device)
+         __throw_system_error(int(errc::operation_not_permitted));
+       else if (_M_owns)
+         __throw_system_error(int(errc::resource_deadlock_would_occur));
+       else
+         {
+           _M_owns = _M_device->try_lock();
+           return _M_owns;
+         }
+      }
+
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+      template<typename _Clock, typename _Duration>
+       bool
+       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
+       {
+         if (!_M_device)
+           __throw_system_error(int(errc::operation_not_permitted));
+         else if (_M_owns)
+           __throw_system_error(int(errc::resource_deadlock_would_occur));
+         else
+           {
+             _M_owns = _M_device->try_lock_until(__atime);
+             return _M_owns;
+           }
+       }
+
+      template<typename _Rep, typename _Period>
+       bool
+       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
+       {
+         if (!_M_device)
+           __throw_system_error(int(errc::operation_not_permitted));
+         else if (_M_owns)
+           __throw_system_error(int(errc::resource_deadlock_would_occur));
+         else
+           {
+             _M_owns = _M_device->try_lock_for(__rtime);
+             return _M_owns;
+           }
+        }
+#endif
+
+      void
+      unlock()
+      {
+       if (!_M_owns)
+         __throw_system_error(int(errc::operation_not_permitted));
+       else if (_M_device)
+         {
+           _M_device->unlock();
+           _M_owns = false;
+         }
+      }
+
+      void
+      swap(unique_lock& __u) noexcept
+      {
+       std::swap(_M_device, __u._M_device);
+       std::swap(_M_owns, __u._M_owns);
+      }
+
+      mutex_type*
+      release() noexcept
+      {
+       mutex_type* __ret = _M_device;
+       _M_device = 0;
+       _M_owns = false;
+       return __ret;
+      }
+
+      bool
+      owns_lock() const noexcept
+      { return _M_owns; }
+
+      explicit operator bool() const noexcept
+      { return owns_lock(); }
+
+      mutex_type*
+      mutex() const noexcept
+      { return _M_device; }
+
+    private:
+      mutex_type*      _M_device;
+      bool             _M_owns;
+    };
+
+  /// Swap overload for unique_lock objects.
+  template<typename _Mutex>
+    inline void
+    swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
+    { __x.swap(__y); }
+
+  // @} group mutexes
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif // C++11
+#endif // _GLIBCXX_UNIQUE_LOCK_H
index 84863a162d6a5210b040f3692ea1613be0aada12..88ab775f771b8fe0427c74a463528ca4fad42b29 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <chrono>
 #include <bits/std_mutex.h>
+#include <bits/unique_lock.h>
 #include <ext/concurrence.h>
 #include <bits/alloc_traits.h>
 #include <bits/allocator.h>
index 71e915cc5a008da5b1a816d5a7f1f0d8aa3f8e20..9318a8d1a5dabcc06010046e87196a2d62ec40ca 100644 (file)
@@ -41,6 +41,7 @@
 #include <type_traits>
 #include <system_error>
 #include <bits/std_mutex.h>
+#include <bits/unique_lock.h>
 #if ! _GTHREAD_USE_MUTEX_TIMEDLOCK
 # include <condition_variable>
 # include <thread>