Currently, vendor-specific availability markup is enabled by default. This means that even when building against trunk libc++, the headers will by default prevent you from using some features that were not released in the dylib on your target platform. This is a source of frustration since people building libc++ from sources are usually not trying to use some vendor's released dylib. For that reason, I've been thinking for a long time that availability annotations should be off by default, which is the primary change that this commit enables. In addition, it reworks the implementation to make it easier for new vendors to add availability annotations for their platform, and it refreshes the documentation to reflect the current state of the codebase. Finally, a CMake configuration option is added to control whether availability annotations should be turned on for the flavor of libc++ being created. The intent is for vendors like Apple to turn it on, and for the upstream libc++ to leave it off (the default). Differential Revision: https://reviews.llvm.org/D90843
106 lines
2.4 KiB
C++
106 lines
2.4 KiB
C++
// -*- C++ -*-
|
|
//===--------------------------- latch -----------------------------------===//
|
|
//
|
|
// 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_LATCH
|
|
#define _LIBCPP_LATCH
|
|
|
|
/*
|
|
latch synopsis
|
|
|
|
namespace std
|
|
{
|
|
|
|
class latch
|
|
{
|
|
public:
|
|
constexpr explicit latch(ptrdiff_t __expected);
|
|
~latch();
|
|
|
|
latch(const latch&) = delete;
|
|
latch& operator=(const latch&) = delete;
|
|
|
|
void count_down(ptrdiff_t __update = 1);
|
|
bool try_wait() const noexcept;
|
|
void wait() const;
|
|
void arrive_and_wait(ptrdiff_t __update = 1);
|
|
|
|
private:
|
|
ptrdiff_t __counter; // exposition only
|
|
};
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
#include <__config>
|
|
#include <__availability>
|
|
#include <atomic>
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
|
#pragma GCC system_header
|
|
#endif
|
|
|
|
#ifdef _LIBCPP_HAS_NO_THREADS
|
|
# error <latch> is not supported on this single threaded system
|
|
#endif
|
|
|
|
#if _LIBCPP_STD_VER >= 14
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
class latch
|
|
{
|
|
__atomic_base<ptrdiff_t> __a;
|
|
|
|
public:
|
|
static constexpr ptrdiff_t max() noexcept {
|
|
return numeric_limits<ptrdiff_t>::max();
|
|
}
|
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
constexpr explicit latch(ptrdiff_t __expected) : __a(__expected) { }
|
|
|
|
~latch() = default;
|
|
latch(const latch&) = delete;
|
|
latch& operator=(const latch&) = delete;
|
|
|
|
inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
|
|
void count_down(ptrdiff_t __update = 1)
|
|
{
|
|
auto const __old = __a.fetch_sub(__update, memory_order_release);
|
|
if(__old == __update)
|
|
__a.notify_all();
|
|
}
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
bool try_wait() const noexcept
|
|
{
|
|
return 0 == __a.load(memory_order_acquire);
|
|
}
|
|
inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
|
|
void wait() const
|
|
{
|
|
auto const __test_fn = [=]() -> bool {
|
|
return try_wait();
|
|
};
|
|
__cxx_atomic_wait(&__a.__a_, __test_fn);
|
|
}
|
|
inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
|
|
void arrive_and_wait(ptrdiff_t __update = 1)
|
|
{
|
|
count_down(__update);
|
|
wait();
|
|
}
|
|
};
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
#endif // _LIBCPP_STD_VER >= 14
|
|
|
|
#endif //_LIBCPP_LATCH
|