// std::mutex implementation -*- C++ -*-
-// Copyright (C) 2003-2016 Free Software Foundation, Inc.
+// Copyright (C) 2003-2021 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
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
-/** @file bits/mutex.h
+/** @file bits/std_mutex.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{mutex}
*/
#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)
{
}
native_handle_type
- native_handle()
+ native_handle() noexcept
{ return &_M_mutex; }
};
+ // Implementation details for std::condition_variable
+ class __condvar
+ {
+ using timespec = __gthread_time_t;
+
+ public:
+ __condvar() noexcept
+ {
+#ifndef __GTHREAD_COND_INIT
+ __GTHREAD_COND_INIT_FUNCTION(&_M_cond);
+#endif
+ }
+
+ ~__condvar()
+ {
+ int __e __attribute__((__unused__)) = __gthread_cond_destroy(&_M_cond);
+ __glibcxx_assert(__e != EBUSY); // threads are still blocked
+ }
+
+ __condvar(const __condvar&) = delete;
+ __condvar& operator=(const __condvar&) = delete;
+
+ __gthread_cond_t* native_handle() noexcept { return &_M_cond; }
+
+ // Expects: Calling thread has locked __m.
+ void
+ wait(mutex& __m) noexcept
+ {
+ int __e __attribute__((__unused__))
+ = __gthread_cond_wait(&_M_cond, __m.native_handle());
+ __glibcxx_assert(__e == 0);
+ }
+
+ void
+ wait_until(mutex& __m, timespec& __abs_time) noexcept
+ {
+ __gthread_cond_timedwait(&_M_cond, __m.native_handle(), &__abs_time);
+ }
+
+#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
+ void
+ wait_until(mutex& __m, clockid_t __clock, timespec& __abs_time) noexcept
+ {
+ pthread_cond_clockwait(&_M_cond, __m.native_handle(), __clock,
+ &__abs_time);
+ }
+#endif
+
+ void
+ notify_one() noexcept
+ {
+ int __e __attribute__((__unused__)) = __gthread_cond_signal(&_M_cond);
+ __glibcxx_assert(__e == 0);
+ }
+
+ void
+ notify_all() noexcept
+ {
+ int __e __attribute__((__unused__)) = __gthread_cond_broadcast(&_M_cond);
+ __glibcxx_assert(__e == 0);
+ }
+
+ protected:
+#ifdef __GTHREAD_COND_INIT
+ __gthread_cond_t _M_cond = __GTHREAD_COND_INIT;
+#else
+ __gthread_cond_t _M_cond;
+#endif
+ };
+
#endif // _GLIBCXX_HAS_GTHREADS
/// Do not acquire ownership of the mutex.
struct adopt_lock_t { explicit adopt_lock_t() = default; };
/// Tag used to prevent a scoped lock from acquiring ownership of a mutex.
- constexpr defer_lock_t defer_lock { };
+ _GLIBCXX17_INLINE constexpr defer_lock_t defer_lock { };
/// Tag used to prevent a scoped lock from blocking if a mutex is locked.
- constexpr try_to_lock_t try_to_lock { };
+ _GLIBCXX17_INLINE constexpr try_to_lock_t try_to_lock { };
/// Tag used to make a scoped lock take ownership of a locked mutex.
- constexpr adopt_lock_t adopt_lock { };
+ _GLIBCXX17_INLINE constexpr adopt_lock_t adopt_lock { };
/** @brief A simple scoped lock type.
*
explicit lock_guard(mutex_type& __m) : _M_device(__m)
{ _M_device.lock(); }
- lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m)
+ lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m)
{ } // calling thread owns mutex
~lock_guard()
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)
- : _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