brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.4 KiB · 8c02e34 Raw
454 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_SHARED_MUTEX11#define _LIBCPP_SHARED_MUTEX12 13/*14    shared_mutex synopsis15 16// C++1y17 18namespace std19{20 21class shared_mutex      // C++1722{23public:24    shared_mutex();25    ~shared_mutex();26 27    shared_mutex(const shared_mutex&) = delete;28    shared_mutex& operator=(const shared_mutex&) = delete;29 30    // Exclusive ownership31    void lock(); // blocking32    bool try_lock();33    void unlock();34 35    // Shared ownership36    void lock_shared(); // blocking37    bool try_lock_shared();38    void unlock_shared();39 40    typedef implementation-defined native_handle_type; // See 30.2.341    native_handle_type native_handle(); // See 30.2.342};43 44class shared_timed_mutex45{46public:47    shared_timed_mutex();48    ~shared_timed_mutex();49 50    shared_timed_mutex(const shared_timed_mutex&) = delete;51    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;52 53    // Exclusive ownership54    void lock(); // blocking55    bool try_lock();56    template <class Rep, class Period>57        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);58    template <class Clock, class Duration>59        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);60    void unlock();61 62    // Shared ownership63    void lock_shared(); // blocking64    bool try_lock_shared();65    template <class Rep, class Period>66        bool67        try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);68    template <class Clock, class Duration>69        bool70        try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);71    void unlock_shared();72};73 74template <class Mutex>75class shared_lock76{77public:78    typedef Mutex mutex_type;79 80    // Shared locking81    shared_lock() noexcept;82    explicit shared_lock(mutex_type& m); // blocking83    shared_lock(mutex_type& m, defer_lock_t) noexcept;84    shared_lock(mutex_type& m, try_to_lock_t);85    shared_lock(mutex_type& m, adopt_lock_t);86    template <class Clock, class Duration>87        shared_lock(mutex_type& m,88                    const chrono::time_point<Clock, Duration>& abs_time);89    template <class Rep, class Period>90        shared_lock(mutex_type& m,91                    const chrono::duration<Rep, Period>& rel_time);92    ~shared_lock();93 94    shared_lock(shared_lock const&) = delete;95    shared_lock& operator=(shared_lock const&) = delete;96 97    shared_lock(shared_lock&& u) noexcept;98    shared_lock& operator=(shared_lock&& u) noexcept;99 100    void lock(); // blocking101    bool try_lock();102    template <class Rep, class Period>103        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);104    template <class Clock, class Duration>105        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);106    void unlock();107 108    // Setters109    void swap(shared_lock& u) noexcept;110    mutex_type* release() noexcept;111 112    // Getters113    bool owns_lock() const noexcept;114    explicit operator bool () const noexcept;115    mutex_type* mutex() const noexcept;116};117 118template <class Mutex>119    void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;120 121}  // std122 123*/124 125#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)126#  include <__cxx03/__config>127#else128#  include <__config>129 130#  if _LIBCPP_HAS_THREADS131 132#    include <__chrono/duration.h>133#    include <__chrono/steady_clock.h>134#    include <__chrono/time_point.h>135#    include <__condition_variable/condition_variable.h>136#    include <__memory/addressof.h>137#    include <__mutex/mutex.h>138#    include <__mutex/tag_types.h>139#    include <__mutex/unique_lock.h>140#    include <__system_error/throw_system_error.h>141#    include <__utility/swap.h>142#    include <cerrno>143#    include <version>144 145_LIBCPP_PUSH_MACROS146#    include <__undef_macros>147 148#    if _LIBCPP_STD_VER >= 14149 150#      if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)151#        pragma GCC system_header152#      endif153 154_LIBCPP_BEGIN_NAMESPACE_STD155 156struct _LIBCPP_EXPORTED_FROM_ABI __shared_mutex_base {157  mutex __mut_;158  condition_variable __gate1_;159  condition_variable __gate2_;160  unsigned __state_;161 162  static const unsigned __write_entered_ = 1U << (sizeof(unsigned) * __CHAR_BIT__ - 1);163  static const unsigned __n_readers_     = ~__write_entered_;164 165  __shared_mutex_base();166  _LIBCPP_HIDE_FROM_ABI ~__shared_mutex_base() = default;167 168  __shared_mutex_base(const __shared_mutex_base&)            = delete;169  __shared_mutex_base& operator=(const __shared_mutex_base&) = delete;170 171  // Exclusive ownership172  void lock(); // blocking173  bool try_lock();174  void unlock();175 176  // Shared ownership177  void lock_shared(); // blocking178  bool try_lock_shared();179  void unlock_shared();180 181  //     typedef implementation-defined native_handle_type; // See 30.2.3182  //     native_handle_type native_handle(); // See 30.2.3183};184 185#      if _LIBCPP_STD_VER >= 17186class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_CAPABILITY("shared_mutex") shared_mutex {187  __shared_mutex_base __base_;188 189public:190  _LIBCPP_HIDE_FROM_ABI shared_mutex() : __base_() {}191  _LIBCPP_HIDE_FROM_ABI ~shared_mutex() = default;192 193  shared_mutex(const shared_mutex&)            = delete;194  shared_mutex& operator=(const shared_mutex&) = delete;195 196  // Exclusive ownership197  _LIBCPP_ACQUIRE_CAPABILITY() _LIBCPP_HIDE_FROM_ABI void lock() { return __base_.lock(); }198  _LIBCPP_TRY_ACQUIRE_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool try_lock() { return __base_.try_lock(); }199  _LIBCPP_RELEASE_CAPABILITY _LIBCPP_HIDE_FROM_ABI void unlock() { return __base_.unlock(); }200 201  // Shared ownership202  _LIBCPP_ACQUIRE_SHARED_CAPABILITY _LIBCPP_HIDE_FROM_ABI void lock_shared() { return __base_.lock_shared(); }203  _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool try_lock_shared() {204    return __base_.try_lock_shared();205  }206  _LIBCPP_RELEASE_SHARED_CAPABILITY _LIBCPP_HIDE_FROM_ABI void unlock_shared() { return __base_.unlock_shared(); }207 208  //     typedef __shared_mutex_base::native_handle_type native_handle_type;209  //     _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return __base::unlock_shared(); }210};211#      endif212 213class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_CAPABILITY("shared_timed_mutex") shared_timed_mutex {214  __shared_mutex_base __base_;215 216public:217  shared_timed_mutex();218  _LIBCPP_HIDE_FROM_ABI ~shared_timed_mutex() = default;219 220  shared_timed_mutex(const shared_timed_mutex&)            = delete;221  shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;222 223  // Exclusive ownership224  void lock() _LIBCPP_ACQUIRE_CAPABILITY();225  _LIBCPP_TRY_ACQUIRE_CAPABILITY(true) bool try_lock();226  template <class _Rep, class _Period>227  _LIBCPP_TRY_ACQUIRE_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool228  try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) {229    return try_lock_until(chrono::steady_clock::now() + __rel_time);230  }231 232  template <class _Clock, class _Duration>233  _LIBCPP_TRY_ACQUIRE_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool234  try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) {235    unique_lock<mutex> __lk(__base_.__mut_);236    if (__base_.__state_ & __base_.__write_entered_) {237      while (true) {238        cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time);239        if ((__base_.__state_ & __base_.__write_entered_) == 0)240          break;241        if (__status == cv_status::timeout)242          return false;243      }244    }245    __base_.__state_ |= __base_.__write_entered_;246    if (__base_.__state_ & __base_.__n_readers_) {247      while (true) {248        cv_status __status = __base_.__gate2_.wait_until(__lk, __abs_time);249        if ((__base_.__state_ & __base_.__n_readers_) == 0)250          break;251        if (__status == cv_status::timeout) {252          __base_.__state_ &= ~__base_.__write_entered_;253          __base_.__gate1_.notify_all();254          return false;255        }256      }257    }258    return true;259  }260 261  _LIBCPP_RELEASE_CAPABILITY void unlock();262 263  // Shared ownership264  _LIBCPP_ACQUIRE_SHARED_CAPABILITY void lock_shared();265  _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(true) bool try_lock_shared();266  template <class _Rep, class _Period>267  _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool268  try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) {269    return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);270  }271 272  template <class _Clock, class _Duration>273  _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool274  try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time) {275    unique_lock<mutex> __lk(__base_.__mut_);276    if ((__base_.__state_ & __base_.__write_entered_) ||277        (__base_.__state_ & __base_.__n_readers_) == __base_.__n_readers_) {278      while (true) {279        cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time);280        if ((__base_.__state_ & __base_.__write_entered_) == 0 &&281            (__base_.__state_ & __base_.__n_readers_) < __base_.__n_readers_)282          break;283        if (__status == cv_status::timeout)284          return false;285      }286    }287    unsigned __num_readers = (__base_.__state_ & __base_.__n_readers_) + 1;288    __base_.__state_ &= ~__base_.__n_readers_;289    __base_.__state_ |= __num_readers;290    return true;291  }292 293  _LIBCPP_RELEASE_SHARED_CAPABILITY void unlock_shared();294};295 296template <class _Mutex>297class shared_lock {298public:299  typedef _Mutex mutex_type;300 301private:302  mutex_type* __m_;303  bool __owns_;304 305public:306  _LIBCPP_HIDE_FROM_ABI shared_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}307 308  _LIBCPP_HIDE_FROM_ABI explicit shared_lock(mutex_type& __m) : __m_(std::addressof(__m)), __owns_(true) {309    __m_->lock_shared();310  }311 312  _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT313      : __m_(std::addressof(__m)),314        __owns_(false) {}315 316  _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, try_to_lock_t)317      : __m_(std::addressof(__m)), __owns_(__m.try_lock_shared()) {}318 319  _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, adopt_lock_t) : __m_(std::addressof(__m)), __owns_(true) {}320 321  template <class _Clock, class _Duration>322  _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __abs_time)323      : __m_(std::addressof(__m)), __owns_(__m.try_lock_shared_until(__abs_time)) {}324 325  template <class _Rep, class _Period>326  _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __rel_time)327      : __m_(std::addressof(__m)), __owns_(__m.try_lock_shared_for(__rel_time)) {}328 329  _LIBCPP_HIDE_FROM_ABI ~shared_lock() {330    if (__owns_)331      __m_->unlock_shared();332  }333 334  shared_lock(shared_lock const&)            = delete;335  shared_lock& operator=(shared_lock const&) = delete;336 337  _LIBCPP_HIDE_FROM_ABI shared_lock(shared_lock&& __u) _NOEXCEPT : __m_(__u.__m_), __owns_(__u.__owns_) {338    __u.__m_    = nullptr;339    __u.__owns_ = false;340  }341 342  _LIBCPP_HIDE_FROM_ABI shared_lock& operator=(shared_lock&& __u) _NOEXCEPT {343    if (__owns_)344      __m_->unlock_shared();345    __m_        = nullptr;346    __owns_     = false;347    __m_        = __u.__m_;348    __owns_     = __u.__owns_;349    __u.__m_    = nullptr;350    __u.__owns_ = false;351    return *this;352  }353 354  _LIBCPP_HIDE_FROM_ABI void lock();355  _LIBCPP_HIDE_FROM_ABI bool try_lock();356  template <class _Rep, class _Period>357  _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time);358  template <class _Clock, class _Duration>359  _LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);360  _LIBCPP_HIDE_FROM_ABI void unlock();361 362  // Setters363  _LIBCPP_HIDE_FROM_ABI void swap(shared_lock& __u) _NOEXCEPT {364    std::swap(__m_, __u.__m_);365    std::swap(__owns_, __u.__owns_);366  }367 368  _LIBCPP_HIDE_FROM_ABI mutex_type* release() _NOEXCEPT {369    mutex_type* __m = __m_;370    __m_            = nullptr;371    __owns_         = false;372    return __m;373  }374 375  // Getters376  _LIBCPP_HIDE_FROM_ABI bool owns_lock() const _NOEXCEPT { return __owns_; }377 378  _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __owns_; }379 380  _LIBCPP_HIDE_FROM_ABI mutex_type* mutex() const _NOEXCEPT { return __m_; }381};382_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(shared_lock);383 384template <class _Mutex>385void shared_lock<_Mutex>::lock() {386  if (__m_ == nullptr)387    std::__throw_system_error(EPERM, "shared_lock::lock: references null mutex");388  if (__owns_)389    std::__throw_system_error(EDEADLK, "shared_lock::lock: already locked");390  __m_->lock_shared();391  __owns_ = true;392}393 394template <class _Mutex>395bool shared_lock<_Mutex>::try_lock() {396  if (__m_ == nullptr)397    std::__throw_system_error(EPERM, "shared_lock::try_lock: references null mutex");398  if (__owns_)399    std::__throw_system_error(EDEADLK, "shared_lock::try_lock: already locked");400  __owns_ = __m_->try_lock_shared();401  return __owns_;402}403 404template <class _Mutex>405template <class _Rep, class _Period>406bool shared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) {407  if (__m_ == nullptr)408    std::__throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex");409  if (__owns_)410    std::__throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked");411  __owns_ = __m_->try_lock_shared_for(__d);412  return __owns_;413}414 415template <class _Mutex>416template <class _Clock, class _Duration>417bool shared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {418  if (__m_ == nullptr)419    std::__throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex");420  if (__owns_)421    std::__throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked");422  __owns_ = __m_->try_lock_shared_until(__t);423  return __owns_;424}425 426template <class _Mutex>427void shared_lock<_Mutex>::unlock() {428  if (!__owns_)429    std::__throw_system_error(EPERM, "shared_lock::unlock: not locked");430  __m_->unlock_shared();431  __owns_ = false;432}433 434template <class _Mutex>435inline _LIBCPP_HIDE_FROM_ABI void swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT {436  __x.swap(__y);437}438 439_LIBCPP_END_NAMESPACE_STD440 441#    endif // _LIBCPP_STD_VER >= 14442 443_LIBCPP_POP_MACROS444 445#  endif // _LIBCPP_HAS_THREADS446 447#  if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20448#    include <optional>449#    include <system_error>450#  endif451#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)452 453#endif // _LIBCPP_SHARED_MUTEX454