// -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef _LIBCPP___CXX03_MUTEX #define _LIBCPP___CXX03_MUTEX /* mutex synopsis namespace std { class mutex { public: constexpr mutex() noexcept; ~mutex(); mutex(const mutex&) = delete; mutex& operator=(const mutex&) = delete; void lock(); bool try_lock(); void unlock(); typedef pthread_mutex_t* native_handle_type; native_handle_type native_handle(); }; class recursive_mutex { public: recursive_mutex(); ~recursive_mutex(); recursive_mutex(const recursive_mutex&) = delete; recursive_mutex& operator=(const recursive_mutex&) = delete; void lock(); bool try_lock() noexcept; void unlock(); typedef pthread_mutex_t* native_handle_type; native_handle_type native_handle(); }; class timed_mutex { public: timed_mutex(); ~timed_mutex(); timed_mutex(const timed_mutex&) = delete; timed_mutex& operator=(const timed_mutex&) = delete; void lock(); bool try_lock(); template bool try_lock_for(const chrono::duration& rel_time); template bool try_lock_until(const chrono::time_point& abs_time); void unlock(); }; class recursive_timed_mutex { public: recursive_timed_mutex(); ~recursive_timed_mutex(); recursive_timed_mutex(const recursive_timed_mutex&) = delete; recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; void lock(); bool try_lock() noexcept; template bool try_lock_for(const chrono::duration& rel_time); template bool try_lock_until(const chrono::time_point& abs_time); void unlock(); }; struct defer_lock_t { explicit defer_lock_t() = default; }; struct try_to_lock_t { explicit try_to_lock_t() = default; }; struct adopt_lock_t { explicit adopt_lock_t() = default; }; inline constexpr defer_lock_t defer_lock{}; inline constexpr try_to_lock_t try_to_lock{}; inline constexpr adopt_lock_t adopt_lock{}; template class lock_guard { public: typedef Mutex mutex_type; explicit lock_guard(mutex_type& m); lock_guard(mutex_type& m, adopt_lock_t); ~lock_guard(); lock_guard(lock_guard const&) = delete; lock_guard& operator=(lock_guard const&) = delete; }; template class scoped_lock // C++17 { public: using mutex_type = Mutex; // Only if sizeof...(MutexTypes) == 1 explicit scoped_lock(MutexTypes&... m); scoped_lock(adopt_lock_t, MutexTypes&... m); ~scoped_lock(); scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; private: tuple pm; // exposition only }; template class unique_lock { public: typedef Mutex mutex_type; unique_lock() noexcept; explicit unique_lock(mutex_type& m); unique_lock(mutex_type& m, defer_lock_t) noexcept; unique_lock(mutex_type& m, try_to_lock_t); unique_lock(mutex_type& m, adopt_lock_t); template unique_lock(mutex_type& m, const chrono::time_point& abs_time); template unique_lock(mutex_type& m, const chrono::duration& rel_time); ~unique_lock(); unique_lock(unique_lock const&) = delete; unique_lock& operator=(unique_lock const&) = delete; unique_lock(unique_lock&& u) noexcept; unique_lock& operator=(unique_lock&& u) noexcept; void lock(); bool try_lock(); template bool try_lock_for(const chrono::duration& rel_time); template bool try_lock_until(const chrono::time_point& abs_time); void unlock(); void swap(unique_lock& u) noexcept; mutex_type* release() noexcept; bool owns_lock() const noexcept; explicit operator bool () const noexcept; mutex_type* mutex() const noexcept; }; template void swap(unique_lock& x, unique_lock& y) noexcept; template int try_lock(L1&, L2&, L3&...); template void lock(L1&, L2&, L3&...); struct once_flag { constexpr once_flag() noexcept; once_flag(const once_flag&) = delete; once_flag& operator=(const once_flag&) = delete; }; template void call_once(once_flag& flag, Callable&& func, Args&&... args); } // std */ #include <__cxx03/__chrono/steady_clock.h> #include <__cxx03/__chrono/time_point.h> #include <__cxx03/__condition_variable/condition_variable.h> #include <__cxx03/__config> #include <__cxx03/__memory/shared_ptr.h> #include <__cxx03/__mutex/lock_guard.h> #include <__cxx03/__mutex/mutex.h> #include <__cxx03/__mutex/once_flag.h> #include <__cxx03/__mutex/tag_types.h> #include <__cxx03/__mutex/unique_lock.h> #include <__cxx03/__thread/id.h> #include <__cxx03/__thread/support.h> #include <__cxx03/__utility/forward.h> #include <__cxx03/cstddef> #include <__cxx03/limits> #include <__cxx03/version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__cxx03/__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_HAS_NO_THREADS class _LIBCPP_EXPORTED_FROM_ABI recursive_mutex { __libcpp_recursive_mutex_t __m_; public: recursive_mutex(); ~recursive_mutex(); recursive_mutex(const recursive_mutex&) = delete; recursive_mutex& operator=(const recursive_mutex&) = delete; void lock(); bool try_lock() _NOEXCEPT; void unlock() _NOEXCEPT; typedef __libcpp_recursive_mutex_t* native_handle_type; _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; } }; class _LIBCPP_EXPORTED_FROM_ABI timed_mutex { mutex __m_; condition_variable __cv_; bool __locked_; public: timed_mutex(); ~timed_mutex(); timed_mutex(const timed_mutex&) = delete; timed_mutex& operator=(const timed_mutex&) = delete; public: void lock(); bool try_lock() _NOEXCEPT; template _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) { return try_lock_until(chrono::steady_clock::now() + __d); } template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); void unlock() _NOEXCEPT; }; template bool timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; unique_lock __lk(__m_); bool __no_timeout = _Clock::now() < __t; while (__no_timeout && __locked_) __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; if (!__locked_) { __locked_ = true; return true; } return false; } class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex { mutex __m_; condition_variable __cv_; size_t __count_; __thread_id __id_; public: recursive_timed_mutex(); ~recursive_timed_mutex(); recursive_timed_mutex(const recursive_timed_mutex&) = delete; recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; void lock(); bool try_lock() _NOEXCEPT; template _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) { return try_lock_until(chrono::steady_clock::now() + __d); } template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); void unlock() _NOEXCEPT; }; template bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; __thread_id __id = this_thread::get_id(); unique_lock __lk(__m_); if (__id == __id_) { if (__count_ == numeric_limits::max()) return false; ++__count_; return true; } bool __no_timeout = _Clock::now() < __t; while (__no_timeout && __count_ != 0) __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; if (__count_ == 0) { __count_ = 1; __id_ = __id; return true; } return false; } template _LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) { unique_lock<_L0> __u0(__l0, try_to_lock_t()); if (__u0.owns_lock()) { if (__l1.try_lock()) { __u0.release(); return -1; } else return 1; } return 0; } template _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) { while (true) { { unique_lock<_L0> __u0(__l0); if (__l1.try_lock()) { __u0.release(); break; } } __libcpp_thread_yield(); { unique_lock<_L1> __u1(__l1); if (__l0.try_lock()) { __u1.release(); break; } } __libcpp_thread_yield(); } } #endif // !_LIBCPP_HAS_NO_THREADS _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) # include <__cxx03/atomic> # include <__cxx03/cstdlib> # include <__cxx03/cstring> # include <__cxx03/ctime> # include <__cxx03/iosfwd> # include <__cxx03/new> # include <__cxx03/stdexcept> # include <__cxx03/system_error> # include <__cxx03/type_traits> # include <__cxx03/typeinfo> #endif #endif // _LIBCPP___CXX03_MUTEX