376 lines · plain
1// -*- C++ -*-2//===----------------------------------------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP___CXX03_MUTEX11#define _LIBCPP___CXX03_MUTEX12 13/*14 mutex synopsis15 16namespace std17{18 19class mutex20{21public:22 constexpr mutex() noexcept;23 ~mutex();24 25 mutex(const mutex&) = delete;26 mutex& operator=(const mutex&) = delete;27 28 void lock();29 bool try_lock();30 void unlock();31 32 typedef pthread_mutex_t* native_handle_type;33 native_handle_type native_handle();34};35 36class recursive_mutex37{38public:39 recursive_mutex();40 ~recursive_mutex();41 42 recursive_mutex(const recursive_mutex&) = delete;43 recursive_mutex& operator=(const recursive_mutex&) = delete;44 45 void lock();46 bool try_lock() noexcept;47 void unlock();48 49 typedef pthread_mutex_t* native_handle_type;50 native_handle_type native_handle();51};52 53class timed_mutex54{55public:56 timed_mutex();57 ~timed_mutex();58 59 timed_mutex(const timed_mutex&) = delete;60 timed_mutex& operator=(const timed_mutex&) = delete;61 62 void lock();63 bool try_lock();64 template <class Rep, class Period>65 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);66 template <class Clock, class Duration>67 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);68 void unlock();69};70 71class recursive_timed_mutex72{73public:74 recursive_timed_mutex();75 ~recursive_timed_mutex();76 77 recursive_timed_mutex(const recursive_timed_mutex&) = delete;78 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;79 80 void lock();81 bool try_lock() noexcept;82 template <class Rep, class Period>83 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);84 template <class Clock, class Duration>85 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);86 void unlock();87};88 89struct defer_lock_t { explicit defer_lock_t() = default; };90struct try_to_lock_t { explicit try_to_lock_t() = default; };91struct adopt_lock_t { explicit adopt_lock_t() = default; };92 93inline constexpr defer_lock_t defer_lock{};94inline constexpr try_to_lock_t try_to_lock{};95inline constexpr adopt_lock_t adopt_lock{};96 97template <class Mutex>98class lock_guard99{100public:101 typedef Mutex mutex_type;102 103 explicit lock_guard(mutex_type& m);104 lock_guard(mutex_type& m, adopt_lock_t);105 ~lock_guard();106 107 lock_guard(lock_guard const&) = delete;108 lock_guard& operator=(lock_guard const&) = delete;109};110 111template <class... MutexTypes>112class scoped_lock // C++17113{114public:115 using mutex_type = Mutex; // Only if sizeof...(MutexTypes) == 1116 117 explicit scoped_lock(MutexTypes&... m);118 scoped_lock(adopt_lock_t, MutexTypes&... m);119 ~scoped_lock();120 scoped_lock(scoped_lock const&) = delete;121 scoped_lock& operator=(scoped_lock const&) = delete;122private:123 tuple<MutexTypes&...> pm; // exposition only124};125 126template <class Mutex>127class unique_lock128{129public:130 typedef Mutex mutex_type;131 unique_lock() noexcept;132 explicit unique_lock(mutex_type& m);133 unique_lock(mutex_type& m, defer_lock_t) noexcept;134 unique_lock(mutex_type& m, try_to_lock_t);135 unique_lock(mutex_type& m, adopt_lock_t);136 template <class Clock, class Duration>137 unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);138 template <class Rep, class Period>139 unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);140 ~unique_lock();141 142 unique_lock(unique_lock const&) = delete;143 unique_lock& operator=(unique_lock const&) = delete;144 145 unique_lock(unique_lock&& u) noexcept;146 unique_lock& operator=(unique_lock&& u) noexcept;147 148 void lock();149 bool try_lock();150 151 template <class Rep, class Period>152 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);153 template <class Clock, class Duration>154 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);155 156 void unlock();157 158 void swap(unique_lock& u) noexcept;159 mutex_type* release() noexcept;160 161 bool owns_lock() const noexcept;162 explicit operator bool () const noexcept;163 mutex_type* mutex() const noexcept;164};165 166template <class Mutex>167 void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;168 169template <class L1, class L2, class... L3>170 int try_lock(L1&, L2&, L3&...);171template <class L1, class L2, class... L3>172 void lock(L1&, L2&, L3&...);173 174struct once_flag175{176 constexpr once_flag() noexcept;177 178 once_flag(const once_flag&) = delete;179 once_flag& operator=(const once_flag&) = delete;180};181 182template<class Callable, class ...Args>183 void call_once(once_flag& flag, Callable&& func, Args&&... args);184 185} // std186 187*/188 189#include <__cxx03/__chrono/steady_clock.h>190#include <__cxx03/__chrono/time_point.h>191#include <__cxx03/__condition_variable/condition_variable.h>192#include <__cxx03/__config>193#include <__cxx03/__memory/shared_ptr.h>194#include <__cxx03/__mutex/lock_guard.h>195#include <__cxx03/__mutex/mutex.h>196#include <__cxx03/__mutex/once_flag.h>197#include <__cxx03/__mutex/tag_types.h>198#include <__cxx03/__mutex/unique_lock.h>199#include <__cxx03/__thread/id.h>200#include <__cxx03/__thread/support.h>201#include <__cxx03/__utility/forward.h>202#include <__cxx03/cstddef>203#include <__cxx03/limits>204#include <__cxx03/version>205 206#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)207# pragma GCC system_header208#endif209 210_LIBCPP_PUSH_MACROS211#include <__cxx03/__undef_macros>212 213_LIBCPP_BEGIN_NAMESPACE_STD214 215#ifndef _LIBCPP_HAS_NO_THREADS216 217class _LIBCPP_EXPORTED_FROM_ABI recursive_mutex {218 __libcpp_recursive_mutex_t __m_;219 220public:221 recursive_mutex();222 ~recursive_mutex();223 224 recursive_mutex(const recursive_mutex&) = delete;225 recursive_mutex& operator=(const recursive_mutex&) = delete;226 227 void lock();228 bool try_lock() _NOEXCEPT;229 void unlock() _NOEXCEPT;230 231 typedef __libcpp_recursive_mutex_t* native_handle_type;232 233 _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; }234};235 236class _LIBCPP_EXPORTED_FROM_ABI timed_mutex {237 mutex __m_;238 condition_variable __cv_;239 bool __locked_;240 241public:242 timed_mutex();243 ~timed_mutex();244 245 timed_mutex(const timed_mutex&) = delete;246 timed_mutex& operator=(const timed_mutex&) = delete;247 248public:249 void lock();250 bool try_lock() _NOEXCEPT;251 template <class _Rep, class _Period>252 _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {253 return try_lock_until(chrono::steady_clock::now() + __d);254 }255 template <class _Clock, class _Duration>256 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool257 try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);258 void unlock() _NOEXCEPT;259};260 261template <class _Clock, class _Duration>262bool timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {263 using namespace chrono;264 unique_lock<mutex> __lk(__m_);265 bool __no_timeout = _Clock::now() < __t;266 while (__no_timeout && __locked_)267 __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;268 if (!__locked_) {269 __locked_ = true;270 return true;271 }272 return false;273}274 275class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex {276 mutex __m_;277 condition_variable __cv_;278 size_t __count_;279 __thread_id __id_;280 281public:282 recursive_timed_mutex();283 ~recursive_timed_mutex();284 285 recursive_timed_mutex(const recursive_timed_mutex&) = delete;286 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;287 288 void lock();289 bool try_lock() _NOEXCEPT;290 template <class _Rep, class _Period>291 _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {292 return try_lock_until(chrono::steady_clock::now() + __d);293 }294 template <class _Clock, class _Duration>295 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool296 try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);297 void unlock() _NOEXCEPT;298};299 300template <class _Clock, class _Duration>301bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {302 using namespace chrono;303 __thread_id __id = this_thread::get_id();304 unique_lock<mutex> __lk(__m_);305 if (__id == __id_) {306 if (__count_ == numeric_limits<size_t>::max())307 return false;308 ++__count_;309 return true;310 }311 bool __no_timeout = _Clock::now() < __t;312 while (__no_timeout && __count_ != 0)313 __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;314 if (__count_ == 0) {315 __count_ = 1;316 __id_ = __id;317 return true;318 }319 return false;320}321 322template <class _L0, class _L1>323_LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) {324 unique_lock<_L0> __u0(__l0, try_to_lock_t());325 if (__u0.owns_lock()) {326 if (__l1.try_lock()) {327 __u0.release();328 return -1;329 } else330 return 1;331 }332 return 0;333}334 335template <class _L0, class _L1>336_LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) {337 while (true) {338 {339 unique_lock<_L0> __u0(__l0);340 if (__l1.try_lock()) {341 __u0.release();342 break;343 }344 }345 __libcpp_thread_yield();346 {347 unique_lock<_L1> __u1(__l1);348 if (__l0.try_lock()) {349 __u1.release();350 break;351 }352 }353 __libcpp_thread_yield();354 }355}356#endif // !_LIBCPP_HAS_NO_THREADS357 358_LIBCPP_END_NAMESPACE_STD359 360_LIBCPP_POP_MACROS361 362#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES)363# include <__cxx03/atomic>364# include <__cxx03/cstdlib>365# include <__cxx03/cstring>366# include <__cxx03/ctime>367# include <__cxx03/iosfwd>368# include <__cxx03/new>369# include <__cxx03/stdexcept>370# include <__cxx03/system_error>371# include <__cxx03/type_traits>372# include <__cxx03/typeinfo>373#endif374 375#endif // _LIBCPP___CXX03_MUTEX376