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