Path: blob/main/contrib/llvm-project/libcxx/src/mutex.cpp
35154 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <__assert>9#include <__thread/id.h>10#include <__utility/exception_guard.h>11#include <limits>12#include <mutex>1314#include "include/atomic_support.h"1516#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)17# pragma comment(lib, "pthread")18#endif1920_LIBCPP_PUSH_MACROS21#include <__undef_macros>2223_LIBCPP_BEGIN_NAMESPACE_STD2425// ~mutex is defined elsewhere2627void mutex::lock() {28int ec = __libcpp_mutex_lock(&__m_);29if (ec)30__throw_system_error(ec, "mutex lock failed");31}3233bool mutex::try_lock() noexcept { return __libcpp_mutex_trylock(&__m_); }3435void mutex::unlock() noexcept {36int ec = __libcpp_mutex_unlock(&__m_);37(void)ec;38_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(39ec == 0, "call to mutex::unlock failed. A possible reason is that the mutex wasn't locked");40}4142// recursive_mutex4344recursive_mutex::recursive_mutex() {45int ec = __libcpp_recursive_mutex_init(&__m_);46if (ec)47__throw_system_error(ec, "recursive_mutex constructor failed");48}4950recursive_mutex::~recursive_mutex() {51int e = __libcpp_recursive_mutex_destroy(&__m_);52(void)e;53_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(e == 0, "call to ~recursive_mutex() failed");54}5556void recursive_mutex::lock() {57int ec = __libcpp_recursive_mutex_lock(&__m_);58if (ec)59__throw_system_error(ec, "recursive_mutex lock failed");60}6162void recursive_mutex::unlock() noexcept {63int e = __libcpp_recursive_mutex_unlock(&__m_);64(void)e;65_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(66e == 0, "call to recursive_mutex::unlock() failed. A possible reason is that the mutex wasn't locked");67}6869bool recursive_mutex::try_lock() noexcept { return __libcpp_recursive_mutex_trylock(&__m_); }7071// timed_mutex7273timed_mutex::timed_mutex() : __locked_(false) {}7475timed_mutex::~timed_mutex() { lock_guard<mutex> _(__m_); }7677void timed_mutex::lock() {78unique_lock<mutex> lk(__m_);79while (__locked_)80__cv_.wait(lk);81__locked_ = true;82}8384bool timed_mutex::try_lock() noexcept {85unique_lock<mutex> lk(__m_, try_to_lock);86if (lk.owns_lock() && !__locked_) {87__locked_ = true;88return true;89}90return false;91}9293void timed_mutex::unlock() noexcept {94lock_guard<mutex> _(__m_);95__locked_ = false;96__cv_.notify_one();97}9899// recursive_timed_mutex100101recursive_timed_mutex::recursive_timed_mutex() : __count_(0), __id_{} {}102103recursive_timed_mutex::~recursive_timed_mutex() { lock_guard<mutex> _(__m_); }104105void recursive_timed_mutex::lock() {106__thread_id id = this_thread::get_id();107unique_lock<mutex> lk(__m_);108if (id == __id_) {109if (__count_ == numeric_limits<size_t>::max())110__throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");111++__count_;112return;113}114while (__count_ != 0)115__cv_.wait(lk);116__count_ = 1;117__id_ = id;118}119120bool recursive_timed_mutex::try_lock() noexcept {121__thread_id id = this_thread::get_id();122unique_lock<mutex> lk(__m_, try_to_lock);123if (lk.owns_lock() && (__count_ == 0 || id == __id_)) {124if (__count_ == numeric_limits<size_t>::max())125return false;126++__count_;127__id_ = id;128return true;129}130return false;131}132133void recursive_timed_mutex::unlock() noexcept {134unique_lock<mutex> lk(__m_);135if (--__count_ == 0) {136__id_.__reset();137lk.unlock();138__cv_.notify_one();139}140}141142_LIBCPP_END_NAMESPACE_STD143144_LIBCPP_POP_MACROS145146147