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