147 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <__assert>10#include <__system_error/throw_system_error.h>11#include <__thread/id.h>12#include <__utility/exception_guard.h>13#include <limits>14#include <mutex>15 16#include "include/atomic_support.h"17 18#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)19# pragma comment(lib, "pthread")20#endif21 22_LIBCPP_PUSH_MACROS23#include <__undef_macros>24 25_LIBCPP_BEGIN_NAMESPACE_STD26 27// ~mutex is defined elsewhere28 29void mutex::lock() {30 int ec = __libcpp_mutex_lock(&__m_);31 if (ec)32 std::__throw_system_error(ec, "mutex lock failed");33}34 35bool mutex::try_lock() noexcept { return __libcpp_mutex_trylock(&__m_); }36 37void mutex::unlock() noexcept {38 int ec = __libcpp_mutex_unlock(&__m_);39 (void)ec;40 _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(41 ec == 0, "call to mutex::unlock failed. A possible reason is that the mutex wasn't locked");42}43 44// recursive_mutex45 46recursive_mutex::recursive_mutex() {47 int ec = __libcpp_recursive_mutex_init(&__m_);48 if (ec)49 std::__throw_system_error(ec, "recursive_mutex constructor failed");50}51 52recursive_mutex::~recursive_mutex() {53 int e = __libcpp_recursive_mutex_destroy(&__m_);54 (void)e;55 _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(e == 0, "call to ~recursive_mutex() failed");56}57 58void recursive_mutex::lock() {59 int ec = __libcpp_recursive_mutex_lock(&__m_);60 if (ec)61 std::__throw_system_error(ec, "recursive_mutex lock failed");62}63 64void recursive_mutex::unlock() noexcept {65 int e = __libcpp_recursive_mutex_unlock(&__m_);66 (void)e;67 _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(68 e == 0, "call to recursive_mutex::unlock() failed. A possible reason is that the mutex wasn't locked");69}70 71bool recursive_mutex::try_lock() noexcept { return __libcpp_recursive_mutex_trylock(&__m_); }72 73// timed_mutex74 75timed_mutex::timed_mutex() : __locked_(false) {}76 77timed_mutex::~timed_mutex() { lock_guard<mutex> _(__m_); }78 79void timed_mutex::lock() {80 unique_lock<mutex> lk(__m_);81 while (__locked_)82 __cv_.wait(lk);83 __locked_ = true;84}85 86bool timed_mutex::try_lock() noexcept {87 unique_lock<mutex> lk(__m_, try_to_lock);88 if (lk.owns_lock() && !__locked_) {89 __locked_ = true;90 return true;91 }92 return false;93}94 95void timed_mutex::unlock() noexcept {96 lock_guard<mutex> _(__m_);97 __locked_ = false;98 __cv_.notify_one();99}100 101// recursive_timed_mutex102 103recursive_timed_mutex::recursive_timed_mutex() : __count_(0), __id_{} {}104 105recursive_timed_mutex::~recursive_timed_mutex() { lock_guard<mutex> _(__m_); }106 107void recursive_timed_mutex::lock() {108 __thread_id id = this_thread::get_id();109 unique_lock<mutex> lk(__m_);110 if (id == __id_) {111 if (__count_ == numeric_limits<size_t>::max())112 std::__throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");113 ++__count_;114 return;115 }116 while (__count_ != 0)117 __cv_.wait(lk);118 __count_ = 1;119 __id_ = id;120}121 122bool recursive_timed_mutex::try_lock() noexcept {123 __thread_id id = this_thread::get_id();124 unique_lock<mutex> lk(__m_, try_to_lock);125 if (lk.owns_lock() && (__count_ == 0 || id == __id_)) {126 if (__count_ == numeric_limits<size_t>::max())127 return false;128 ++__count_;129 __id_ = id;130 return true;131 }132 return false;133}134 135void recursive_timed_mutex::unlock() noexcept {136 unique_lock<mutex> lk(__m_);137 if (--__count_ == 0) {138 __id_.__reset();139 lk.unlock();140 __cv_.notify_one();141 }142}143 144_LIBCPP_END_NAMESPACE_STD145 146_LIBCPP_POP_MACROS147