1*4d6fc14bSjoerg// -*- C++ -*- 2*4d6fc14bSjoerg//===--------------------------- latch -----------------------------------===// 3*4d6fc14bSjoerg// 4*4d6fc14bSjoerg// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*4d6fc14bSjoerg// See https://llvm.org/LICENSE.txt for license information. 6*4d6fc14bSjoerg// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*4d6fc14bSjoerg// 8*4d6fc14bSjoerg//===----------------------------------------------------------------------===// 9*4d6fc14bSjoerg 10*4d6fc14bSjoerg#ifndef _LIBCPP_LATCH 11*4d6fc14bSjoerg#define _LIBCPP_LATCH 12*4d6fc14bSjoerg 13*4d6fc14bSjoerg/* 14*4d6fc14bSjoerg latch synopsis 15*4d6fc14bSjoerg 16*4d6fc14bSjoergnamespace std 17*4d6fc14bSjoerg{ 18*4d6fc14bSjoerg 19*4d6fc14bSjoerg class latch 20*4d6fc14bSjoerg { 21*4d6fc14bSjoerg public: 22*4d6fc14bSjoerg static constexpr ptrdiff_t max() noexcept; 23*4d6fc14bSjoerg 24*4d6fc14bSjoerg constexpr explicit latch(ptrdiff_t __expected); 25*4d6fc14bSjoerg ~latch(); 26*4d6fc14bSjoerg 27*4d6fc14bSjoerg latch(const latch&) = delete; 28*4d6fc14bSjoerg latch& operator=(const latch&) = delete; 29*4d6fc14bSjoerg 30*4d6fc14bSjoerg void count_down(ptrdiff_t __update = 1); 31*4d6fc14bSjoerg bool try_wait() const noexcept; 32*4d6fc14bSjoerg void wait() const; 33*4d6fc14bSjoerg void arrive_and_wait(ptrdiff_t __update = 1); 34*4d6fc14bSjoerg 35*4d6fc14bSjoerg private: 36*4d6fc14bSjoerg ptrdiff_t __counter; // exposition only 37*4d6fc14bSjoerg }; 38*4d6fc14bSjoerg 39*4d6fc14bSjoerg} 40*4d6fc14bSjoerg 41*4d6fc14bSjoerg*/ 42*4d6fc14bSjoerg 43*4d6fc14bSjoerg#include <__config> 44*4d6fc14bSjoerg#include <__availability> 45*4d6fc14bSjoerg#include <atomic> 46*4d6fc14bSjoerg 47*4d6fc14bSjoerg#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 48*4d6fc14bSjoerg#pragma GCC system_header 49*4d6fc14bSjoerg#endif 50*4d6fc14bSjoerg 51*4d6fc14bSjoerg#ifdef _LIBCPP_HAS_NO_THREADS 52*4d6fc14bSjoerg# error <latch> is not supported on this single threaded system 53*4d6fc14bSjoerg#endif 54*4d6fc14bSjoerg 55*4d6fc14bSjoerg_LIBCPP_PUSH_MACROS 56*4d6fc14bSjoerg#include <__undef_macros> 57*4d6fc14bSjoerg 58*4d6fc14bSjoerg#if _LIBCPP_STD_VER >= 14 59*4d6fc14bSjoerg 60*4d6fc14bSjoerg_LIBCPP_BEGIN_NAMESPACE_STD 61*4d6fc14bSjoerg 62*4d6fc14bSjoergclass latch 63*4d6fc14bSjoerg{ 64*4d6fc14bSjoerg __atomic_base<ptrdiff_t> __a; 65*4d6fc14bSjoerg 66*4d6fc14bSjoergpublic: 67*4d6fc14bSjoerg static constexpr ptrdiff_t max() noexcept { 68*4d6fc14bSjoerg return numeric_limits<ptrdiff_t>::max(); 69*4d6fc14bSjoerg } 70*4d6fc14bSjoerg 71*4d6fc14bSjoerg inline _LIBCPP_INLINE_VISIBILITY 72*4d6fc14bSjoerg constexpr explicit latch(ptrdiff_t __expected) : __a(__expected) { } 73*4d6fc14bSjoerg 74*4d6fc14bSjoerg ~latch() = default; 75*4d6fc14bSjoerg latch(const latch&) = delete; 76*4d6fc14bSjoerg latch& operator=(const latch&) = delete; 77*4d6fc14bSjoerg 78*4d6fc14bSjoerg inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 79*4d6fc14bSjoerg void count_down(ptrdiff_t __update = 1) 80*4d6fc14bSjoerg { 81*4d6fc14bSjoerg auto const __old = __a.fetch_sub(__update, memory_order_release); 82*4d6fc14bSjoerg if(__old == __update) 83*4d6fc14bSjoerg __a.notify_all(); 84*4d6fc14bSjoerg } 85*4d6fc14bSjoerg inline _LIBCPP_INLINE_VISIBILITY 86*4d6fc14bSjoerg bool try_wait() const noexcept 87*4d6fc14bSjoerg { 88*4d6fc14bSjoerg return 0 == __a.load(memory_order_acquire); 89*4d6fc14bSjoerg } 90*4d6fc14bSjoerg inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 91*4d6fc14bSjoerg void wait() const 92*4d6fc14bSjoerg { 93*4d6fc14bSjoerg auto const __test_fn = [=]() -> bool { 94*4d6fc14bSjoerg return try_wait(); 95*4d6fc14bSjoerg }; 96*4d6fc14bSjoerg __cxx_atomic_wait(&__a.__a_, __test_fn); 97*4d6fc14bSjoerg } 98*4d6fc14bSjoerg inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 99*4d6fc14bSjoerg void arrive_and_wait(ptrdiff_t __update = 1) 100*4d6fc14bSjoerg { 101*4d6fc14bSjoerg count_down(__update); 102*4d6fc14bSjoerg wait(); 103*4d6fc14bSjoerg } 104*4d6fc14bSjoerg}; 105*4d6fc14bSjoerg 106*4d6fc14bSjoerg_LIBCPP_END_NAMESPACE_STD 107*4d6fc14bSjoerg 108*4d6fc14bSjoerg#endif // _LIBCPP_STD_VER >= 14 109*4d6fc14bSjoerg 110*4d6fc14bSjoerg_LIBCPP_POP_MACROS 111*4d6fc14bSjoerg 112*4d6fc14bSjoerg#endif //_LIBCPP_LATCH 113