mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-02 14:56:08 +00:00

In preparation for running clang-format on the whole code base, we are also removing mentions of the legacy _LIBCPP_INLINE_VISIBILITY macro in favor of the newer _LIBCPP_HIDE_FROM_ABI. We're still leaving the definition of _LIBCPP_INLINE_VISIBILITY to avoid creating needless breakage in case some older patches are checked-in with mentions of the old macro. After we branch for LLVM 18, we can do another pass to clean up remaining uses of the macro that might have gotten introduced by mistake (if any) and remove the macro itself at the same time. This is just a minor convenience to smooth out the transition as much as possible. See https://discourse.llvm.org/t/rfc-clang-formatting-all-of-libc-once-and-for-all for the clang-format proposal.
355 lines
11 KiB
C++
355 lines
11 KiB
C++
// -*- C++ -*-
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef _LIBCPP_CONDITION_VARIABLE
|
|
#define _LIBCPP_CONDITION_VARIABLE
|
|
|
|
/*
|
|
condition_variable synopsis
|
|
|
|
namespace std
|
|
{
|
|
|
|
enum class cv_status { no_timeout, timeout };
|
|
|
|
class condition_variable
|
|
{
|
|
public:
|
|
condition_variable();
|
|
~condition_variable();
|
|
|
|
condition_variable(const condition_variable&) = delete;
|
|
condition_variable& operator=(const condition_variable&) = delete;
|
|
|
|
void notify_one() noexcept;
|
|
void notify_all() noexcept;
|
|
|
|
void wait(unique_lock<mutex>& lock);
|
|
template <class Predicate>
|
|
void wait(unique_lock<mutex>& lock, Predicate pred);
|
|
|
|
template <class Clock, class Duration>
|
|
cv_status
|
|
wait_until(unique_lock<mutex>& lock,
|
|
const chrono::time_point<Clock, Duration>& abs_time);
|
|
|
|
template <class Clock, class Duration, class Predicate>
|
|
bool
|
|
wait_until(unique_lock<mutex>& lock,
|
|
const chrono::time_point<Clock, Duration>& abs_time,
|
|
Predicate pred);
|
|
|
|
template <class Rep, class Period>
|
|
cv_status
|
|
wait_for(unique_lock<mutex>& lock,
|
|
const chrono::duration<Rep, Period>& rel_time);
|
|
|
|
template <class Rep, class Period, class Predicate>
|
|
bool
|
|
wait_for(unique_lock<mutex>& lock,
|
|
const chrono::duration<Rep, Period>& rel_time,
|
|
Predicate pred);
|
|
|
|
typedef pthread_cond_t* native_handle_type;
|
|
native_handle_type native_handle();
|
|
};
|
|
|
|
void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
|
|
|
|
class condition_variable_any
|
|
{
|
|
public:
|
|
condition_variable_any();
|
|
~condition_variable_any();
|
|
|
|
condition_variable_any(const condition_variable_any&) = delete;
|
|
condition_variable_any& operator=(const condition_variable_any&) = delete;
|
|
|
|
void notify_one() noexcept;
|
|
void notify_all() noexcept;
|
|
|
|
template <class Lock>
|
|
void wait(Lock& lock);
|
|
template <class Lock, class Predicate>
|
|
void wait(Lock& lock, Predicate pred);
|
|
|
|
template <class Lock, class Clock, class Duration>
|
|
cv_status
|
|
wait_until(Lock& lock,
|
|
const chrono::time_point<Clock, Duration>& abs_time);
|
|
|
|
template <class Lock, class Clock, class Duration, class Predicate>
|
|
bool
|
|
wait_until(Lock& lock,
|
|
const chrono::time_point<Clock, Duration>& abs_time,
|
|
Predicate pred);
|
|
|
|
template <class Lock, class Rep, class Period>
|
|
cv_status
|
|
wait_for(Lock& lock,
|
|
const chrono::duration<Rep, Period>& rel_time);
|
|
|
|
template <class Lock, class Rep, class Period, class Predicate>
|
|
bool
|
|
wait_for(Lock& lock,
|
|
const chrono::duration<Rep, Period>& rel_time,
|
|
Predicate pred);
|
|
|
|
// [thread.condvarany.intwait], interruptible waits
|
|
template <class Lock, class Predicate>
|
|
bool wait(Lock& lock, stop_token stoken, Predicate pred); // since C++20
|
|
|
|
template <class Lock, class Clock, class Duration, class Predicate>
|
|
bool wait_until(Lock& lock, stop_token stoken,
|
|
const chrono::time_point<Clock, Duration>& abs_time, Predicate pred); // since C++20
|
|
|
|
template <class Lock, class Rep, class Period, class Predicate>
|
|
bool wait_for(Lock& lock, stop_token stoken,
|
|
const chrono::duration<Rep, Period>& rel_time, Predicate pred); // since C++20
|
|
};
|
|
|
|
} // std
|
|
|
|
*/
|
|
|
|
#include <__assert> // all public C++ headers provide the assertion handler
|
|
#include <__availability>
|
|
#include <__chrono/duration.h>
|
|
#include <__chrono/steady_clock.h>
|
|
#include <__chrono/time_point.h>
|
|
#include <__condition_variable/condition_variable.h>
|
|
#include <__config>
|
|
#include <__memory/shared_ptr.h>
|
|
#include <__memory/unique_ptr.h>
|
|
#include <__mutex/lock_guard.h>
|
|
#include <__mutex/mutex.h>
|
|
#include <__mutex/tag_types.h>
|
|
#include <__mutex/unique_lock.h>
|
|
#include <__stop_token/stop_token.h>
|
|
#include <__utility/move.h>
|
|
#include <version>
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
|
# pragma GCC system_header
|
|
#endif
|
|
|
|
#ifndef _LIBCPP_HAS_NO_THREADS
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
class _LIBCPP_EXPORTED_FROM_ABI condition_variable_any
|
|
{
|
|
condition_variable __cv_;
|
|
shared_ptr<mutex> __mut_;
|
|
public:
|
|
_LIBCPP_HIDE_FROM_ABI
|
|
condition_variable_any();
|
|
|
|
_LIBCPP_HIDE_FROM_ABI
|
|
void notify_one() _NOEXCEPT;
|
|
_LIBCPP_HIDE_FROM_ABI
|
|
void notify_all() _NOEXCEPT;
|
|
|
|
template <class _Lock>
|
|
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
|
|
void wait(_Lock& __lock);
|
|
template <class _Lock, class _Predicate>
|
|
_LIBCPP_HIDE_FROM_ABI
|
|
void wait(_Lock& __lock, _Predicate __pred);
|
|
|
|
template <class _Lock, class _Clock, class _Duration>
|
|
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
|
|
cv_status
|
|
wait_until(_Lock& __lock,
|
|
const chrono::time_point<_Clock, _Duration>& __t);
|
|
|
|
template <class _Lock, class _Clock, class _Duration, class _Predicate>
|
|
bool
|
|
_LIBCPP_HIDE_FROM_ABI
|
|
wait_until(_Lock& __lock,
|
|
const chrono::time_point<_Clock, _Duration>& __t,
|
|
_Predicate __pred);
|
|
|
|
template <class _Lock, class _Rep, class _Period>
|
|
cv_status
|
|
_LIBCPP_HIDE_FROM_ABI
|
|
wait_for(_Lock& __lock,
|
|
const chrono::duration<_Rep, _Period>& __d);
|
|
|
|
template <class _Lock, class _Rep, class _Period, class _Predicate>
|
|
bool
|
|
_LIBCPP_HIDE_FROM_ABI
|
|
wait_for(_Lock& __lock,
|
|
const chrono::duration<_Rep, _Period>& __d,
|
|
_Predicate __pred);
|
|
|
|
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
|
|
|
|
template <class _Lock, class _Predicate>
|
|
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait(_Lock& __lock, stop_token __stoken, _Predicate __pred);
|
|
|
|
template <class _Lock, class _Clock, class _Duration, class _Predicate>
|
|
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait_until(_Lock& __lock, stop_token __stoken,
|
|
const chrono::time_point<_Clock, _Duration>& __abs_time, _Predicate __pred);
|
|
|
|
template <class _Lock, class _Rep, class _Period, class _Predicate>
|
|
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait_for(_Lock& __lock, stop_token __stoken,
|
|
const chrono::duration<_Rep, _Period>& __rel_time, _Predicate __pred);
|
|
|
|
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
|
|
};
|
|
|
|
inline
|
|
condition_variable_any::condition_variable_any()
|
|
: __mut_(make_shared<mutex>()) {}
|
|
|
|
inline
|
|
void
|
|
condition_variable_any::notify_one() _NOEXCEPT
|
|
{
|
|
{lock_guard<mutex> __lx(*__mut_);}
|
|
__cv_.notify_one();
|
|
}
|
|
|
|
inline
|
|
void
|
|
condition_variable_any::notify_all() _NOEXCEPT
|
|
{
|
|
{lock_guard<mutex> __lx(*__mut_);}
|
|
__cv_.notify_all();
|
|
}
|
|
|
|
struct __lock_external
|
|
{
|
|
template <class _Lock>
|
|
_LIBCPP_HIDE_FROM_ABI void operator()(_Lock* __m) {__m->lock();}
|
|
};
|
|
|
|
template <class _Lock>
|
|
void
|
|
condition_variable_any::wait(_Lock& __lock)
|
|
{
|
|
shared_ptr<mutex> __mut = __mut_;
|
|
unique_lock<mutex> __lk(*__mut);
|
|
__lock.unlock();
|
|
unique_ptr<_Lock, __lock_external> __lxx(&__lock);
|
|
lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t());
|
|
__cv_.wait(__lk);
|
|
} // __mut_.unlock(), __lock.lock()
|
|
|
|
template <class _Lock, class _Predicate>
|
|
inline
|
|
void
|
|
condition_variable_any::wait(_Lock& __lock, _Predicate __pred)
|
|
{
|
|
while (!__pred())
|
|
wait(__lock);
|
|
}
|
|
|
|
template <class _Lock, class _Clock, class _Duration>
|
|
cv_status
|
|
condition_variable_any::wait_until(_Lock& __lock,
|
|
const chrono::time_point<_Clock, _Duration>& __t)
|
|
{
|
|
shared_ptr<mutex> __mut = __mut_;
|
|
unique_lock<mutex> __lk(*__mut);
|
|
__lock.unlock();
|
|
unique_ptr<_Lock, __lock_external> __lxx(&__lock);
|
|
lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t());
|
|
return __cv_.wait_until(__lk, __t);
|
|
} // __mut_.unlock(), __lock.lock()
|
|
|
|
template <class _Lock, class _Clock, class _Duration, class _Predicate>
|
|
inline
|
|
bool
|
|
condition_variable_any::wait_until(_Lock& __lock,
|
|
const chrono::time_point<_Clock, _Duration>& __t,
|
|
_Predicate __pred)
|
|
{
|
|
while (!__pred())
|
|
if (wait_until(__lock, __t) == cv_status::timeout)
|
|
return __pred();
|
|
return true;
|
|
}
|
|
|
|
template <class _Lock, class _Rep, class _Period>
|
|
inline
|
|
cv_status
|
|
condition_variable_any::wait_for(_Lock& __lock,
|
|
const chrono::duration<_Rep, _Period>& __d)
|
|
{
|
|
return wait_until(__lock, chrono::steady_clock::now() + __d);
|
|
}
|
|
|
|
template <class _Lock, class _Rep, class _Period, class _Predicate>
|
|
inline
|
|
bool
|
|
condition_variable_any::wait_for(_Lock& __lock,
|
|
const chrono::duration<_Rep, _Period>& __d,
|
|
_Predicate __pred)
|
|
{
|
|
return wait_until(__lock, chrono::steady_clock::now() + __d,
|
|
_VSTD::move(__pred));
|
|
}
|
|
|
|
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
|
|
|
|
template <class _Lock, class _Predicate>
|
|
bool condition_variable_any::wait(_Lock& __lock, stop_token __stoken, _Predicate __pred) {
|
|
while (!__stoken.stop_requested()) {
|
|
if (__pred())
|
|
return true;
|
|
wait(__lock);
|
|
}
|
|
return __pred();
|
|
}
|
|
|
|
template <class _Lock, class _Clock, class _Duration, class _Predicate>
|
|
bool condition_variable_any::wait_until(
|
|
_Lock& __lock, stop_token __stoken, const chrono::time_point<_Clock, _Duration>& __abs_time, _Predicate __pred) {
|
|
while (!__stoken.stop_requested()) {
|
|
if (__pred())
|
|
return true;
|
|
if (wait_until(__lock, __abs_time) == cv_status::timeout)
|
|
return __pred();
|
|
}
|
|
return __pred();
|
|
}
|
|
|
|
template <class _Lock, class _Rep, class _Period, class _Predicate>
|
|
bool condition_variable_any::wait_for(
|
|
_Lock& __lock, stop_token __stoken, const chrono::duration<_Rep, _Period>& __rel_time, _Predicate __pred) {
|
|
return wait_until(__lock, std::move(__stoken), chrono::steady_clock::now() + __rel_time, std::move(__pred));
|
|
}
|
|
|
|
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
|
|
|
|
_LIBCPP_EXPORTED_FROM_ABI void notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>);
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
#endif // !_LIBCPP_HAS_NO_THREADS
|
|
|
|
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
|
|
# include <atomic>
|
|
# include <concepts>
|
|
# include <cstdint>
|
|
# include <cstdlib>
|
|
# include <cstring>
|
|
# include <initializer_list>
|
|
# include <iosfwd>
|
|
# include <new>
|
|
# include <stdexcept>
|
|
# include <system_error>
|
|
# include <type_traits>
|
|
# include <typeinfo>
|
|
#endif
|
|
|
|
#endif // _LIBCPP_CONDITION_VARIABLE
|