llvm-project
145 строк · 3.6 Кб
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include <__assert>10#include <__thread/id.h>11#include <__utility/exception_guard.h>12#include <limits>13#include <mutex>14
15#include "include/atomic_support.h"16
17#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)18# pragma comment(lib, "pthread")19#endif20
21_LIBCPP_PUSH_MACROS
22#include <__undef_macros>23
24_LIBCPP_BEGIN_NAMESPACE_STD
25
26// ~mutex is defined elsewhere
27
28void mutex::lock() {29int ec = __libcpp_mutex_lock(&__m_);30if (ec)31__throw_system_error(ec, "mutex lock failed");32}
33
34bool mutex::try_lock() noexcept { return __libcpp_mutex_trylock(&__m_); }35
36void mutex::unlock() noexcept {37int ec = __libcpp_mutex_unlock(&__m_);38(void)ec;39_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(40ec == 0, "call to mutex::unlock failed. A possible reason is that the mutex wasn't locked");41}
42
43// recursive_mutex
44
45recursive_mutex::recursive_mutex() {46int ec = __libcpp_recursive_mutex_init(&__m_);47if (ec)48__throw_system_error(ec, "recursive_mutex constructor failed");49}
50
51recursive_mutex::~recursive_mutex() {52int e = __libcpp_recursive_mutex_destroy(&__m_);53(void)e;54_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(e == 0, "call to ~recursive_mutex() failed");55}
56
57void recursive_mutex::lock() {58int ec = __libcpp_recursive_mutex_lock(&__m_);59if (ec)60__throw_system_error(ec, "recursive_mutex lock failed");61}
62
63void recursive_mutex::unlock() noexcept {64int e = __libcpp_recursive_mutex_unlock(&__m_);65(void)e;66_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(67e == 0, "call to recursive_mutex::unlock() failed. A possible reason is that the mutex wasn't locked");68}
69
70bool recursive_mutex::try_lock() noexcept { return __libcpp_recursive_mutex_trylock(&__m_); }71
72// timed_mutex
73
74timed_mutex::timed_mutex() : __locked_(false) {}75
76timed_mutex::~timed_mutex() { lock_guard<mutex> _(__m_); }77
78void timed_mutex::lock() {79unique_lock<mutex> lk(__m_);80while (__locked_)81__cv_.wait(lk);82__locked_ = true;83}
84
85bool timed_mutex::try_lock() noexcept {86unique_lock<mutex> lk(__m_, try_to_lock);87if (lk.owns_lock() && !__locked_) {88__locked_ = true;89return true;90}91return false;92}
93
94void timed_mutex::unlock() noexcept {95lock_guard<mutex> _(__m_);96__locked_ = false;97__cv_.notify_one();98}
99
100// recursive_timed_mutex
101
102recursive_timed_mutex::recursive_timed_mutex() : __count_(0), __id_{} {}103
104recursive_timed_mutex::~recursive_timed_mutex() { lock_guard<mutex> _(__m_); }105
106void recursive_timed_mutex::lock() {107__thread_id id = this_thread::get_id();108unique_lock<mutex> lk(__m_);109if (id == __id_) {110if (__count_ == numeric_limits<size_t>::max())111__throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");112++__count_;113return;114}115while (__count_ != 0)116__cv_.wait(lk);117__count_ = 1;118__id_ = id;119}
120
121bool recursive_timed_mutex::try_lock() noexcept {122__thread_id id = this_thread::get_id();123unique_lock<mutex> lk(__m_, try_to_lock);124if (lk.owns_lock() && (__count_ == 0 || id == __id_)) {125if (__count_ == numeric_limits<size_t>::max())126return false;127++__count_;128__id_ = id;129return true;130}131return false;132}
133
134void recursive_timed_mutex::unlock() noexcept {135unique_lock<mutex> lk(__m_);136if (--__count_ == 0) {137__id_.__reset();138lk.unlock();139__cv_.notify_one();140}141}
142
143_LIBCPP_END_NAMESPACE_STD
144
145_LIBCPP_POP_MACROS
146