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