brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.9 KiB · bec0185 Raw
525 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_MUTEX11#define _LIBCPP_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#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)190#  include <__cxx03/mutex>191#else192#  include <__chrono/steady_clock.h>193#  include <__chrono/time_point.h>194#  include <__condition_variable/condition_variable.h>195#  include <__config>196#  include <__mutex/lock_guard.h>197#  include <__mutex/mutex.h>198#  include <__mutex/once_flag.h>199#  include <__mutex/tag_types.h>200#  include <__mutex/unique_lock.h>201#  include <__thread/id.h>202#  include <__thread/support.h>203#  include <__utility/forward.h>204#  include <limits>205#  ifndef _LIBCPP_CXX03_LANG206#    include <tuple>207#  endif208#  include <version>209 210#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)211#    pragma GCC system_header212#  endif213 214_LIBCPP_PUSH_MACROS215#  include <__undef_macros>216 217_LIBCPP_BEGIN_NAMESPACE_STD218 219#  if _LIBCPP_HAS_THREADS220 221class _LIBCPP_EXPORTED_FROM_ABI recursive_mutex {222  __libcpp_recursive_mutex_t __m_;223 224public:225  recursive_mutex();226  ~recursive_mutex();227 228  recursive_mutex(const recursive_mutex&)            = delete;229  recursive_mutex& operator=(const recursive_mutex&) = delete;230 231  void lock();232  [[__nodiscard__]] bool try_lock() _NOEXCEPT;233  void unlock() _NOEXCEPT;234 235  typedef __libcpp_recursive_mutex_t* native_handle_type;236 237  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; }238};239 240class _LIBCPP_EXPORTED_FROM_ABI timed_mutex {241  mutex __m_;242  condition_variable __cv_;243  bool __locked_;244 245public:246  timed_mutex();247  ~timed_mutex();248 249  timed_mutex(const timed_mutex&)            = delete;250  timed_mutex& operator=(const timed_mutex&) = delete;251 252public:253  void lock();254  [[__nodiscard__]] bool try_lock() _NOEXCEPT;255  template <class _Rep, class _Period>256  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {257    return try_lock_until(chrono::steady_clock::now() + __d);258  }259 260  template <class _Clock, class _Duration>261  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {262    using namespace chrono;263    unique_lock<mutex> __lk(__m_);264    bool __no_timeout = _Clock::now() < __t;265    while (__no_timeout && __locked_)266      __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;267    if (!__locked_) {268      __locked_ = true;269      return true;270    }271    return false;272  }273 274  void unlock() _NOEXCEPT;275};276 277class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex {278  mutex __m_;279  condition_variable __cv_;280  size_t __count_;281  __thread_id __id_;282 283public:284  recursive_timed_mutex();285  ~recursive_timed_mutex();286 287  recursive_timed_mutex(const recursive_timed_mutex&)            = delete;288  recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;289 290  void lock();291  [[__nodiscard__]] bool try_lock() _NOEXCEPT;292  template <class _Rep, class _Period>293  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {294    return try_lock_until(chrono::steady_clock::now() + __d);295  }296 297  template <class _Clock, class _Duration>298  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {299    using namespace chrono;300    __thread_id __id = this_thread::get_id();301    unique_lock<mutex> __lk(__m_);302    if (__id == __id_) {303      if (__count_ == numeric_limits<size_t>::max())304        return false;305      ++__count_;306      return true;307    }308    bool __no_timeout = _Clock::now() < __t;309    while (__no_timeout && __count_ != 0)310      __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;311    if (__count_ == 0) {312      __count_ = 1;313      __id_    = __id;314      return true;315    }316    return false;317  }318 319  void unlock() _NOEXCEPT;320};321 322template <class _L0, class _L1>323[[__nodiscard__]] _LIBCPP_NO_THREAD_SAFETY_ANALYSIS _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 335#    ifndef _LIBCPP_CXX03_LANG336 337template <class _L0, class _L1, class _L2, class... _L3>338[[__nodiscard__]] _LIBCPP_NO_THREAD_SAFETY_ANALYSIS339    _LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {340  int __r = 0;341  unique_lock<_L0> __u0(__l0, try_to_lock);342  if (__u0.owns_lock()) {343    __r = std::try_lock(__l1, __l2, __l3...);344    if (__r == -1)345      __u0.release();346    else347      ++__r;348  }349  return __r;350}351 352#    endif // _LIBCPP_CXX03_LANG353 354// We're using unique_lock to implement the functions, which thread annotations don't support. So we have to disable355// the analysis inside the function.356template <class _L0, class _L1>357_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1)358    _LIBCPP_ACQUIRE_CAPABILITY(__l0, __l1) {359  while (true) {360    {361      unique_lock<_L0> __u0(__l0);362      if (__l1.try_lock()) {363        __u0.release();364        break;365      }366    }367    __libcpp_thread_yield();368    {369      unique_lock<_L1> __u1(__l1);370      if (__l0.try_lock()) {371        __u1.release();372        break;373      }374    }375    __libcpp_thread_yield();376  }377}378 379#    ifndef _LIBCPP_CXX03_LANG380 381template <class _L0, class _L1, class _L2, class... _L3>382_LIBCPP_NO_THREAD_SAFETY_ANALYSIS void __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {383  while (true) {384    switch (__i) {385    case 0: {386      unique_lock<_L0> __u0(__l0);387      __i = std::try_lock(__l1, __l2, __l3...);388      if (__i == -1) {389        __u0.release();390        return;391      }392    }393      ++__i;394      __libcpp_thread_yield();395      break;396    case 1: {397      unique_lock<_L1> __u1(__l1);398      __i = std::try_lock(__l2, __l3..., __l0);399      if (__i == -1) {400        __u1.release();401        return;402      }403    }404      if (__i == sizeof...(_L3) + 1)405        __i = 0;406      else407        __i += 2;408      __libcpp_thread_yield();409      break;410    default:411      std::__lock_first(__i - 2, __l2, __l3..., __l0, __l1);412      return;413    }414  }415}416 417// We're using unique_lock to implement the functions, which thread annotations don't support. So we have to disable418// the analysis inside the function.419template <class _L0, class _L1, class _L2, class... _L3>420_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)421#      if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 2101422    _LIBCPP_ACQUIRE_CAPABILITY(__l0, __l1, __l2, __l3...)423#      endif424{425  std::__lock_first(0, __l0, __l1, __l2, __l3...);426}427 428#    endif // _LIBCPP_CXX03_LANG429 430#    if _LIBCPP_STD_VER >= 17431template <class... _Mutexes>432class scoped_lock;433 434template <>435class scoped_lock<> {436public:437  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock() {}438  ~scoped_lock() = default;439 440  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t) {}441 442  scoped_lock(scoped_lock const&)            = delete;443  scoped_lock& operator=(scoped_lock const&) = delete;444};445 446template <class _Mutex>447class _LIBCPP_SCOPED_LOCKABLE scoped_lock<_Mutex> {448public:449  typedef _Mutex mutex_type;450 451private:452  mutex_type& __m_;453 454public:455  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(mutex_type& __m) _LIBCPP_ACQUIRE_CAPABILITY(__m)456      : __m_(__m) {457    __m_.lock();458  }459 460  _LIBCPP_RELEASE_CAPABILITY _LIBCPP_HIDE_FROM_ABI ~scoped_lock() { __m_.unlock(); }461 462  [[nodiscard]]463  _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_REQUIRES_CAPABILITY(__m)464      : __m_(__m) {}465 466  scoped_lock(scoped_lock const&)            = delete;467  scoped_lock& operator=(scoped_lock const&) = delete;468};469 470template <class... _MArgs>471class scoped_lock {472  static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required");473  typedef tuple<_MArgs&...> _MutexTuple;474 475public:476  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) {477    std::lock(__margs...);478  }479 480  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {}481 482  _LIBCPP_HIDE_FROM_ABI ~scoped_lock() { __unlock_unpack(make_index_sequence<sizeof...(_MArgs)>(), __t_); }483 484  scoped_lock(scoped_lock const&)            = delete;485  scoped_lock& operator=(scoped_lock const&) = delete;486 487private:488  template <size_t... _Indx>489  _LIBCPP_HIDE_FROM_ABI static void __unlock_unpack(index_sequence<_Indx...>, _MutexTuple& __mt) {490    (std::get<_Indx>(__mt).unlock(), ...);491  }492 493  _MutexTuple __t_;494};495_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock);496 497#    endif // _LIBCPP_STD_VER >= 17498#  endif   // _LIBCPP_HAS_THREADS499 500_LIBCPP_END_NAMESPACE_STD501 502_LIBCPP_POP_MACROS503 504#  if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23505#    include <typeinfo>506#  endif507 508#  if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20509#    include <atomic>510#    include <concepts>511#    include <cstdlib>512#    include <cstring>513#    include <ctime>514#    include <initializer_list>515#    include <iosfwd>516#    include <new>517#    include <optional>518#    include <stdexcept>519#    include <system_error>520#    include <type_traits>521#  endif522#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)523 524#endif // _LIBCPP_MUTEX525