123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- // -*- 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_LATCH
- #define _LIBCPP_LATCH
- /*
- latch synopsis
- namespace std
- {
- class latch
- {
- public:
- static constexpr ptrdiff_t max() noexcept;
- 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 <__assert> // all public C++ headers provide the assertion handler
- #include <__atomic/atomic_base.h>
- #include <__atomic/atomic_sync.h>
- #include <__atomic/memory_order.h>
- #include <__availability>
- #include <__config>
- #include <cstddef>
- #include <limits>
- #include <version>
- #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
- # pragma GCC system_header
- #endif
- #ifdef _LIBCPP_HAS_NO_THREADS
- # error "<latch> is not supported since libc++ has been configured without support for threads."
- #endif
- _LIBCPP_PUSH_MACROS
- #include <__undef_macros>
- #if _LIBCPP_STD_VER >= 14
- _LIBCPP_BEGIN_NAMESPACE_STD
- class latch
- {
- __atomic_base<ptrdiff_t> __a_;
- public:
- static _LIBCPP_HIDE_FROM_ABI constexpr ptrdiff_t max() noexcept {
- return numeric_limits<ptrdiff_t>::max();
- }
- inline _LIBCPP_INLINE_VISIBILITY
- constexpr explicit latch(ptrdiff_t __expected) : __a_(__expected)
- {
- _LIBCPP_ASSERT_UNCATEGORIZED(__expected >= 0,
- "latch::latch(ptrdiff_t): latch cannot be "
- "initialized with a negative value");
- _LIBCPP_ASSERT_UNCATEGORIZED(__expected <= max(),
- "latch::latch(ptrdiff_t): latch cannot be "
- "initialized with a value greater than max()");
- }
- _LIBCPP_HIDE_FROM_ABI ~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)
- {
- _LIBCPP_ASSERT_UNCATEGORIZED(
- __update >= 0, "latch::count_down called with a negative value");
- auto const __old = __a_.fetch_sub(__update, memory_order_release);
- _LIBCPP_ASSERT_UNCATEGORIZED(
- __update <= __old, "latch::count_down called with a value greater "
- "than the internal counter");
- 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
- {
- __cxx_atomic_wait(&__a_.__a_, [this]() -> bool {
- return try_wait();
- });
- }
- inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
- void arrive_and_wait(ptrdiff_t __update = 1)
- {
- _LIBCPP_ASSERT_UNCATEGORIZED(
- __update >= 0, "latch::arrive_and_wait called with a negative value");
- // other preconditions on __update are checked in count_down()
- count_down(__update);
- wait();
- }
- };
- _LIBCPP_END_NAMESPACE_STD
- #endif // _LIBCPP_STD_VER >= 14
- _LIBCPP_POP_MACROS
- #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
- # include <atomic>
- #endif
- #endif //_LIBCPP_LATCH
|