codekingpro/portable-devtools
114k
1// -*- C++ -*-2//===------------------------ shared_mutex --------------------------------===//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 _LIBCUDACXX_SHARED_MUTEX11#define _LIBCUDACXX_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#include <__config>126#include <version>127 128_LIBCUDACXX_PUSH_MACROS129#include <__undef_macros>130 131 132#if _LIBCUDACXX_STD_VER > 11 || defined(_LIBCUDACXX_BUILDING_LIBRARY)133 134#include <__mutex_base>135 136#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)137# pragma GCC system_header138#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)139# pragma clang system_header140#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)141# pragma system_header142#endif // no system header143 144#ifdef _LIBCUDACXX_HAS_NO_THREADS145#error <shared_mutex> is not supported on this single threaded system146#else // !_LIBCUDACXX_HAS_NO_THREADS147 148_LIBCUDACXX_BEGIN_NAMESPACE_STD149 150struct _LIBCUDACXX_TYPE_VIS _LIBCUDACXX_AVAILABILITY_SHARED_MUTEX _LIBCUDACXX_THREAD_SAFETY_ANNOTATION(capability("shared_mutex"))151__shared_mutex_base152{153 mutex __mut_;154 condition_variable __gate1_;155 condition_variable __gate2_;156 unsigned __state_;157 158 static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1);159 static const unsigned __n_readers_ = ~__write_entered_;160 161 __shared_mutex_base();162 _LIBCUDACXX_INLINE_VISIBILITY ~__shared_mutex_base() = default;163 164 __shared_mutex_base(const __shared_mutex_base&) = delete;165 __shared_mutex_base& operator=(const __shared_mutex_base&) = delete;166 167 // Exclusive ownership168 void lock() _LIBCUDACXX_THREAD_SAFETY_ANNOTATION(acquire_capability()); // blocking169 bool try_lock() _LIBCUDACXX_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));170 void unlock() _LIBCUDACXX_THREAD_SAFETY_ANNOTATION(release_capability());171 172 // Shared ownership173 void lock_shared() _LIBCUDACXX_THREAD_SAFETY_ANNOTATION(acquire_shared_capability()); // blocking174 bool try_lock_shared() _LIBCUDACXX_THREAD_SAFETY_ANNOTATION(try_acquire_shared_capability(true));175 void unlock_shared() _LIBCUDACXX_THREAD_SAFETY_ANNOTATION(release_shared_capability());176 177// typedef implementation-defined native_handle_type; // See 30.2.3178// native_handle_type native_handle(); // See 30.2.3179};180 181 182#if _LIBCUDACXX_STD_VER > 14183class _LIBCUDACXX_TYPE_VIS _LIBCUDACXX_AVAILABILITY_SHARED_MUTEX shared_mutex184{185 __shared_mutex_base __base;186public:187 _LIBCUDACXX_INLINE_VISIBILITY shared_mutex() : __base() {}188 _LIBCUDACXX_INLINE_VISIBILITY ~shared_mutex() = default;189 190 shared_mutex(const shared_mutex&) = delete;191 shared_mutex& operator=(const shared_mutex&) = delete;192 193 // Exclusive ownership194 _LIBCUDACXX_INLINE_VISIBILITY void lock() { return __base.lock(); }195 _LIBCUDACXX_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); }196 _LIBCUDACXX_INLINE_VISIBILITY void unlock() { return __base.unlock(); }197 198 // Shared ownership199 _LIBCUDACXX_INLINE_VISIBILITY void lock_shared() { return __base.lock_shared(); }200 _LIBCUDACXX_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); }201 _LIBCUDACXX_INLINE_VISIBILITY void unlock_shared() { return __base.unlock_shared(); }202 203// typedef __shared_mutex_base::native_handle_type native_handle_type;204// _LIBCUDACXX_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); }205};206#endif207 208 209class _LIBCUDACXX_TYPE_VIS _LIBCUDACXX_AVAILABILITY_SHARED_MUTEX shared_timed_mutex210{211 __shared_mutex_base __base;212public:213 shared_timed_mutex();214 _LIBCUDACXX_INLINE_VISIBILITY ~shared_timed_mutex() = default;215 216 shared_timed_mutex(const shared_timed_mutex&) = delete;217 shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;218 219 // Exclusive ownership220 void lock();221 bool try_lock();222 template <class _Rep, class _Period>223 _LIBCUDACXX_INLINE_VISIBILITY224 bool225 try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)226 {227 return try_lock_until(chrono::steady_clock::now() + __rel_time);228 }229 template <class _Clock, class _Duration>230 _LIBCUDACXX_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS231 bool232 try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);233 void unlock();234 235 // Shared ownership236 void lock_shared();237 bool try_lock_shared();238 template <class _Rep, class _Period>239 _LIBCUDACXX_INLINE_VISIBILITY240 bool241 try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)242 {243 return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);244 }245 template <class _Clock, class _Duration>246 _LIBCUDACXX_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS247 bool248 try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);249 void unlock_shared();250};251 252template <class _Clock, class _Duration>253bool254shared_timed_mutex::try_lock_until(255 const chrono::time_point<_Clock, _Duration>& __abs_time)256{257 unique_lock<mutex> __lk(__base.__mut_);258 if (__base.__state_ & __base.__write_entered_)259 {260 while (true)261 {262 cv_status __status = __base.__gate1_.wait_until(__lk, __abs_time);263 if ((__base.__state_ & __base.__write_entered_) == 0)264 break;265 if (__status == cv_status::timeout)266 return false;267 }268 }269 __base.__state_ |= __base.__write_entered_;270 if (__base.__state_ & __base.__n_readers_)271 {272 while (true)273 {274 cv_status __status = __base.__gate2_.wait_until(__lk, __abs_time);275 if ((__base.__state_ & __base.__n_readers_) == 0)276 break;277 if (__status == cv_status::timeout)278 {279 __base.__state_ &= ~__base.__write_entered_;280 __base.__gate1_.notify_all();281 return false;282 }283 }284 }285 return true;286}287 288template <class _Clock, class _Duration>289bool290shared_timed_mutex::try_lock_shared_until(291 const chrono::time_point<_Clock, _Duration>& __abs_time)292{293 unique_lock<mutex> __lk(__base.__mut_);294 if ((__base.__state_ & __base.__write_entered_) || (__base.__state_ & __base.__n_readers_) == __base.__n_readers_)295 {296 while (true)297 {298 cv_status status = __base.__gate1_.wait_until(__lk, __abs_time);299 if ((__base.__state_ & __base.__write_entered_) == 0 &&300 (__base.__state_ & __base.__n_readers_) < __base.__n_readers_)301 break;302 if (status == cv_status::timeout)303 return false;304 }305 }306 unsigned __num_readers = (__base.__state_ & __base.__n_readers_) + 1;307 __base.__state_ &= ~__base.__n_readers_;308 __base.__state_ |= __num_readers;309 return true;310}311 312template <class _Mutex>313class shared_lock314{315public:316 typedef _Mutex mutex_type;317 318private:319 mutex_type* __m_;320 bool __owns_;321 322public:323 _LIBCUDACXX_INLINE_VISIBILITY324 shared_lock() noexcept325 : __m_(nullptr),326 __owns_(false)327 {}328 329 _LIBCUDACXX_INLINE_VISIBILITY330 explicit shared_lock(mutex_type& __m)331 : __m_(_CUDA_VSTD::addressof(__m)),332 __owns_(true)333 {__m_->lock_shared();}334 335 _LIBCUDACXX_INLINE_VISIBILITY336 shared_lock(mutex_type& __m, defer_lock_t) noexcept337 : __m_(_CUDA_VSTD::addressof(__m)),338 __owns_(false)339 {}340 341 _LIBCUDACXX_INLINE_VISIBILITY342 shared_lock(mutex_type& __m, try_to_lock_t)343 : __m_(_CUDA_VSTD::addressof(__m)),344 __owns_(__m.try_lock_shared())345 {}346 347 _LIBCUDACXX_INLINE_VISIBILITY348 shared_lock(mutex_type& __m, adopt_lock_t)349 : __m_(_CUDA_VSTD::addressof(__m)),350 __owns_(true)351 {}352 353 template <class _Clock, class _Duration>354 _LIBCUDACXX_INLINE_VISIBILITY355 shared_lock(mutex_type& __m,356 const chrono::time_point<_Clock, _Duration>& __abs_time)357 : __m_(_CUDA_VSTD::addressof(__m)),358 __owns_(__m.try_lock_shared_until(__abs_time))359 {}360 361 template <class _Rep, class _Period>362 _LIBCUDACXX_INLINE_VISIBILITY363 shared_lock(mutex_type& __m,364 const chrono::duration<_Rep, _Period>& __rel_time)365 : __m_(_CUDA_VSTD::addressof(__m)),366 __owns_(__m.try_lock_shared_for(__rel_time))367 {}368 369 _LIBCUDACXX_INLINE_VISIBILITY370 ~shared_lock()371 {372 if (__owns_)373 __m_->unlock_shared();374 }375 376 shared_lock(shared_lock const&) = delete;377 shared_lock& operator=(shared_lock const&) = delete;378 379 _LIBCUDACXX_INLINE_VISIBILITY380 shared_lock(shared_lock&& __u) noexcept381 : __m_(__u.__m_),382 __owns_(__u.__owns_)383 {384 __u.__m_ = nullptr;385 __u.__owns_ = false;386 }387 388 _LIBCUDACXX_INLINE_VISIBILITY389 shared_lock& operator=(shared_lock&& __u) noexcept390 {391 if (__owns_)392 __m_->unlock_shared();393 __m_ = nullptr;394 __owns_ = false;395 __m_ = __u.__m_;396 __owns_ = __u.__owns_;397 __u.__m_ = nullptr;398 __u.__owns_ = false;399 return *this;400 }401 402 void lock();403 bool try_lock();404 template <class Rep, class Period>405 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);406 template <class Clock, class Duration>407 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);408 void unlock();409 410 // Setters411 _LIBCUDACXX_INLINE_VISIBILITY412 void swap(shared_lock& __u) noexcept413 {414 _CUDA_VSTD::swap(__m_, __u.__m_);415 _CUDA_VSTD::swap(__owns_, __u.__owns_);416 }417 418 _LIBCUDACXX_INLINE_VISIBILITY419 mutex_type* release() noexcept420 {421 mutex_type* __m = __m_;422 __m_ = nullptr;423 __owns_ = false;424 return __m;425 }426 427 // Getters428 _LIBCUDACXX_INLINE_VISIBILITY429 bool owns_lock() const noexcept {return __owns_;}430 431 _LIBCUDACXX_INLINE_VISIBILITY432 explicit operator bool () const noexcept {return __owns_;}433 434 _LIBCUDACXX_INLINE_VISIBILITY435 mutex_type* mutex() const noexcept {return __m_;}436};437 438template <class _Mutex>439void440shared_lock<_Mutex>::lock()441{442 if (__m_ == nullptr)443 __throw_system_error(EPERM, "shared_lock::lock: references null mutex");444 if (__owns_)445 __throw_system_error(EDEADLK, "shared_lock::lock: already locked");446 __m_->lock_shared();447 __owns_ = true;448}449 450template <class _Mutex>451bool452shared_lock<_Mutex>::try_lock()453{454 if (__m_ == nullptr)455 __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex");456 if (__owns_)457 __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked");458 __owns_ = __m_->try_lock_shared();459 return __owns_;460}461 462template <class _Mutex>463template <class _Rep, class _Period>464bool465shared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)466{467 if (__m_ == nullptr)468 __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex");469 if (__owns_)470 __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked");471 __owns_ = __m_->try_lock_shared_for(__d);472 return __owns_;473}474 475template <class _Mutex>476template <class _Clock, class _Duration>477bool478shared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)479{480 if (__m_ == nullptr)481 __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex");482 if (__owns_)483 __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked");484 __owns_ = __m_->try_lock_shared_until(__t);485 return __owns_;486}487 488template <class _Mutex>489void490shared_lock<_Mutex>::unlock()491{492 if (!__owns_)493 __throw_system_error(EPERM, "shared_lock::unlock: not locked");494 __m_->unlock_shared();495 __owns_ = false;496}497 498template <class _Mutex>499inline _LIBCUDACXX_INLINE_VISIBILITY500void501swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) noexcept502 {__x.swap(__y);}503 504_LIBCUDACXX_END_NAMESPACE_STD505 506#endif // !_LIBCUDACXX_HAS_NO_THREADS507 508#endif // _LIBCUDACXX_STD_VER > 11509 510_LIBCUDACXX_POP_MACROS511 512#endif // _LIBCUDACXX_SHARED_MUTEX513 