| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include "mutex" |
| | #include "limits" |
| | #include "system_error" |
| | #include "include/atomic_support.h" |
| | #include "__undef_macros" |
| |
|
| | #ifndef _LIBCUDACXX_HAS_NO_THREADS |
| | #if defined(__unix__) && !defined(__ANDROID__) && defined(__ELF__) && defined(_LIBCUDACXX_HAS_COMMENT_LIB_PRAGMA) |
| | #pragma comment(lib, "pthread") |
| | #endif |
| | #endif |
| |
|
| | _LIBCUDACXX_BEGIN_NAMESPACE_STD |
| | #ifndef _LIBCUDACXX_HAS_NO_THREADS |
| |
|
| | const defer_lock_t defer_lock{}; |
| | const try_to_lock_t try_to_lock{}; |
| | const adopt_lock_t adopt_lock{}; |
| |
|
| | |
| |
|
| | void |
| | mutex::lock() |
| | { |
| | int ec = __libcpp_mutex_lock(&__m_); |
| | if (ec) |
| | __throw_system_error(ec, "mutex lock failed"); |
| | } |
| |
|
| | bool |
| | mutex::try_lock() _NOEXCEPT |
| | { |
| | return __libcpp_mutex_trylock(&__m_); |
| | } |
| |
|
| | void |
| | mutex::unlock() _NOEXCEPT |
| | { |
| | int ec = __libcpp_mutex_unlock(&__m_); |
| | (void)ec; |
| | _LIBCUDACXX_ASSERT(ec == 0, "call to mutex::unlock failed"); |
| | } |
| |
|
| | |
| |
|
| | recursive_mutex::recursive_mutex() |
| | { |
| | int ec = __libcpp_recursive_mutex_init(&__m_); |
| | if (ec) |
| | __throw_system_error(ec, "recursive_mutex constructor failed"); |
| | } |
| |
|
| | recursive_mutex::~recursive_mutex() |
| | { |
| | int e = __libcpp_recursive_mutex_destroy(&__m_); |
| | (void)e; |
| | _LIBCUDACXX_ASSERT(e == 0, "call to ~recursive_mutex() failed"); |
| | } |
| |
|
| | void |
| | recursive_mutex::lock() |
| | { |
| | int ec = __libcpp_recursive_mutex_lock(&__m_); |
| | if (ec) |
| | __throw_system_error(ec, "recursive_mutex lock failed"); |
| | } |
| |
|
| | void |
| | recursive_mutex::unlock() _NOEXCEPT |
| | { |
| | int e = __libcpp_recursive_mutex_unlock(&__m_); |
| | (void)e; |
| | _LIBCUDACXX_ASSERT(e == 0, "call to recursive_mutex::unlock() failed"); |
| | } |
| |
|
| | bool |
| | recursive_mutex::try_lock() _NOEXCEPT |
| | { |
| | return __libcpp_recursive_mutex_trylock(&__m_); |
| | } |
| |
|
| | |
| |
|
| | timed_mutex::timed_mutex() |
| | : __locked_(false) |
| | { |
| | } |
| |
|
| | timed_mutex::~timed_mutex() |
| | { |
| | lock_guard<mutex> _(__m_); |
| | } |
| |
|
| | void |
| | timed_mutex::lock() |
| | { |
| | unique_lock<mutex> lk(__m_); |
| | while (__locked_) |
| | __cv_.wait(lk); |
| | __locked_ = true; |
| | } |
| |
|
| | bool |
| | timed_mutex::try_lock() _NOEXCEPT |
| | { |
| | unique_lock<mutex> lk(__m_, try_to_lock); |
| | if (lk.owns_lock() && !__locked_) |
| | { |
| | __locked_ = true; |
| | return true; |
| | } |
| | return false; |
| | } |
| |
|
| | void |
| | timed_mutex::unlock() _NOEXCEPT |
| | { |
| | lock_guard<mutex> _(__m_); |
| | __locked_ = false; |
| | __cv_.notify_one(); |
| | } |
| |
|
| | |
| |
|
| | recursive_timed_mutex::recursive_timed_mutex() |
| | : __count_(0), |
| | __id_{} |
| | { |
| | } |
| |
|
| | recursive_timed_mutex::~recursive_timed_mutex() |
| | { |
| | lock_guard<mutex> _(__m_); |
| | } |
| |
|
| | void |
| | recursive_timed_mutex::lock() |
| | { |
| | __thread_id id = this_thread::get_id(); |
| | unique_lock<mutex> lk(__m_); |
| | if (id ==__id_) |
| | { |
| | if (__count_ == numeric_limits<size_t>::max()) |
| | __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached"); |
| | ++__count_; |
| | return; |
| | } |
| | while (__count_ != 0) |
| | __cv_.wait(lk); |
| | __count_ = 1; |
| | __id_ = id; |
| | } |
| |
|
| | bool |
| | recursive_timed_mutex::try_lock() _NOEXCEPT |
| | { |
| | __thread_id id = this_thread::get_id(); |
| | unique_lock<mutex> lk(__m_, try_to_lock); |
| | if (lk.owns_lock() && (__count_ == 0 || id == __id_)) |
| | { |
| | if (__count_ == numeric_limits<size_t>::max()) |
| | return false; |
| | ++__count_; |
| | __id_ = id; |
| | return true; |
| | } |
| | return false; |
| | } |
| |
|
| | void |
| | recursive_timed_mutex::unlock() _NOEXCEPT |
| | { |
| | unique_lock<mutex> lk(__m_); |
| | if (--__count_ == 0) |
| | { |
| | __id_.__reset(); |
| | lk.unlock(); |
| | __cv_.notify_one(); |
| | } |
| | } |
| |
|
| | #endif |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | #ifndef _LIBCUDACXX_HAS_NO_THREADS |
| | _LIBCUDACXX_SAFE_STATIC static __libcpp_mutex_t mut = _LIBCUDACXX_MUTEX_INITIALIZER; |
| | _LIBCUDACXX_SAFE_STATIC static __libcpp_condvar_t cv = _LIBCUDACXX_CONDVAR_INITIALIZER; |
| | #endif |
| |
|
| | void __call_once(volatile once_flag::_State_type& flag, void* arg, |
| | void (*func)(void*)) |
| | { |
| | #if defined(_LIBCUDACXX_HAS_NO_THREADS) |
| | if (flag == 0) |
| | { |
| | #ifndef _LIBCUDACXX_NO_EXCEPTIONS |
| | try |
| | { |
| | #endif |
| | flag = 1; |
| | func(arg); |
| | flag = ~once_flag::_State_type(0); |
| | #ifndef _LIBCUDACXX_NO_EXCEPTIONS |
| | } |
| | catch (...) |
| | { |
| | flag = 0; |
| | throw; |
| | } |
| | #endif |
| | } |
| | #else |
| | __libcpp_mutex_lock(&mut); |
| | while (flag == 1) |
| | __libcpp_condvar_wait(&cv, &mut); |
| | if (flag == 0) |
| | { |
| | #ifndef _LIBCUDACXX_NO_EXCEPTIONS |
| | try |
| | { |
| | #endif |
| | __libcpp_relaxed_store(&flag, once_flag::_State_type(1)); |
| | __libcpp_mutex_unlock(&mut); |
| | func(arg); |
| | __libcpp_mutex_lock(&mut); |
| | __libcpp_atomic_store(&flag, ~once_flag::_State_type(0), |
| | _AO_Release); |
| | __libcpp_mutex_unlock(&mut); |
| | __libcpp_condvar_broadcast(&cv); |
| | #ifndef _LIBCUDACXX_NO_EXCEPTIONS |
| | } |
| | catch (...) |
| | { |
| | __libcpp_mutex_lock(&mut); |
| | __libcpp_relaxed_store(&flag, once_flag::_State_type(0)); |
| | __libcpp_mutex_unlock(&mut); |
| | __libcpp_condvar_broadcast(&cv); |
| | throw; |
| | } |
| | #endif |
| | } |
| | else |
| | __libcpp_mutex_unlock(&mut); |
| | #endif |
| | } |
| |
|
| | _LIBCUDACXX_END_NAMESPACE_STD |
| |
|