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 <__atomic/atomic_base.h> 45#include <__atomic/atomic_sync.h> 46#include <__atomic/memory_order.h> 47#include <__availability> 48#include <__config> 49#include <cstddef> 50#include <limits> 51#include <version> 52 53#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 54# pragma GCC system_header 55#endif 56 57#ifdef _LIBCPP_HAS_NO_THREADS 58# error "<latch> is not supported since libc++ has been configured without support for threads." 59#endif 60 61_LIBCPP_PUSH_MACROS 62#include <__undef_macros> 63 64#if _LIBCPP_STD_VER >= 14 65 66_LIBCPP_BEGIN_NAMESPACE_STD 67 68class latch 69{ 70 __atomic_base<ptrdiff_t> __a_; 71 72public: 73 static _LIBCPP_HIDE_FROM_ABI constexpr ptrdiff_t max() noexcept { 74 return numeric_limits<ptrdiff_t>::max(); 75 } 76 77 inline _LIBCPP_INLINE_VISIBILITY 78 constexpr explicit latch(ptrdiff_t __expected) : __a_(__expected) { } 79 80 _LIBCPP_HIDE_FROM_ABI ~latch() = default; 81 latch(const latch&) = delete; 82 latch& operator=(const latch&) = delete; 83 84 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 85 void count_down(ptrdiff_t __update = 1) 86 { 87 auto const __old = __a_.fetch_sub(__update, memory_order_release); 88 if(__old == __update) 89 __a_.notify_all(); 90 } 91 inline _LIBCPP_INLINE_VISIBILITY 92 bool try_wait() const noexcept 93 { 94 return 0 == __a_.load(memory_order_acquire); 95 } 96 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 97 void wait() const 98 { 99 __cxx_atomic_wait(&__a_.__a_, [&]() -> bool { 100 return try_wait(); 101 }); 102 } 103 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 104 void arrive_and_wait(ptrdiff_t __update = 1) 105 { 106 count_down(__update); 107 wait(); 108 } 109}; 110 111_LIBCPP_END_NAMESPACE_STD 112 113#endif // _LIBCPP_STD_VER >= 14 114 115_LIBCPP_POP_MACROS 116 117#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 118# include <atomic> 119#endif 120 121#endif //_LIBCPP_LATCH 122