1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP_LATCH 11#define _LIBCPP_LATCH 12 13/* 14 latch synopsis 15 16namespace std 17{ 18 19 class latch 20 { 21 public: 22 static constexpr ptrdiff_t max() noexcept; 23 24 constexpr explicit latch(ptrdiff_t __expected); 25 ~latch(); 26 27 latch(const latch&) = delete; 28 latch& operator=(const latch&) = delete; 29 30 void count_down(ptrdiff_t __update = 1); 31 bool try_wait() const noexcept; 32 void wait() const; 33 void arrive_and_wait(ptrdiff_t __update = 1); 34 35 private: 36 ptrdiff_t __counter; // exposition only 37 }; 38 39} 40 41*/ 42 43#include <__assert> // all public C++ headers provide the assertion handler 44#include <__availability> 45#include <__config> 46#include <atomic> 47#include <version> 48 49#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 50# pragma GCC system_header 51#endif 52 53#ifdef _LIBCPP_HAS_NO_THREADS 54# error <latch> is not supported on this single threaded system 55#endif 56 57_LIBCPP_PUSH_MACROS 58#include <__undef_macros> 59 60#if _LIBCPP_STD_VER >= 14 61 62_LIBCPP_BEGIN_NAMESPACE_STD 63 64class latch 65{ 66 __atomic_base<ptrdiff_t> __a; 67 68public: 69 static constexpr ptrdiff_t max() noexcept { 70 return numeric_limits<ptrdiff_t>::max(); 71 } 72 73 inline _LIBCPP_INLINE_VISIBILITY 74 constexpr explicit latch(ptrdiff_t __expected) : __a(__expected) { } 75 76 ~latch() = default; 77 latch(const latch&) = delete; 78 latch& operator=(const latch&) = delete; 79 80 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 81 void count_down(ptrdiff_t __update = 1) 82 { 83 auto const __old = __a.fetch_sub(__update, memory_order_release); 84 if(__old == __update) 85 __a.notify_all(); 86 } 87 inline _LIBCPP_INLINE_VISIBILITY 88 bool try_wait() const noexcept 89 { 90 return 0 == __a.load(memory_order_acquire); 91 } 92 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 93 void wait() const 94 { 95 __cxx_atomic_wait(&__a.__a_, [&]() -> bool { 96 return try_wait(); 97 }); 98 } 99 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 100 void arrive_and_wait(ptrdiff_t __update = 1) 101 { 102 count_down(__update); 103 wait(); 104 } 105}; 106 107_LIBCPP_END_NAMESPACE_STD 108 109#endif // _LIBCPP_STD_VER >= 14 110 111_LIBCPP_POP_MACROS 112 113#endif //_LIBCPP_LATCH 114