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 constexpr explicit latch(ptrdiff_t __expected); 23 ~latch(); 24 25 latch(const latch&) = delete; 26 latch& operator=(const latch&) = delete; 27 28 void count_down(ptrdiff_t __update = 1); 29 bool try_wait() const noexcept; 30 void wait() const; 31 void arrive_and_wait(ptrdiff_t __update = 1); 32 33 private: 34 ptrdiff_t __counter; // exposition only 35 }; 36 37} 38 39*/ 40 41#include <__config> 42#include <atomic> 43 44#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 45#pragma GCC system_header 46#endif 47 48#ifdef _LIBCPP_HAS_NO_THREADS 49# error <latch> is not supported on this single threaded system 50#endif 51 52#if _LIBCPP_STD_VER >= 14 53 54_LIBCPP_BEGIN_NAMESPACE_STD 55 56class latch 57{ 58 __atomic_base<ptrdiff_t> __a; 59 60public: 61 static constexpr ptrdiff_t max() noexcept { 62 return numeric_limits<ptrdiff_t>::max(); 63 } 64 65 inline _LIBCPP_INLINE_VISIBILITY 66 constexpr explicit latch(ptrdiff_t __expected) : __a(__expected) { } 67 68 ~latch() = default; 69 latch(const latch&) = delete; 70 latch& operator=(const latch&) = delete; 71 72 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 73 void count_down(ptrdiff_t __update = 1) 74 { 75 auto const __old = __a.fetch_sub(__update, memory_order_release); 76 if(__old == __update) 77 __a.notify_all(); 78 } 79 inline _LIBCPP_INLINE_VISIBILITY 80 bool try_wait() const noexcept 81 { 82 return 0 == __a.load(memory_order_acquire); 83 } 84 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 85 void wait() const 86 { 87 auto const __test_fn = [=]() -> bool { 88 return try_wait(); 89 }; 90 __cxx_atomic_wait(&__a.__a_, __test_fn); 91 } 92 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 93 void arrive_and_wait(ptrdiff_t __update = 1) 94 { 95 count_down(__update); 96 wait(); 97 } 98}; 99 100_LIBCPP_END_NAMESPACE_STD 101 102#endif // _LIBCPP_STD_VER >= 14 103 104#endif //_LIBCPP_LATCH 105