154fa9ecdSOlivier Giroux// -*- C++ -*- 2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===// 354fa9ecdSOlivier Giroux// 454fa9ecdSOlivier Giroux// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 554fa9ecdSOlivier Giroux// See https://llvm.org/LICENSE.txt for license information. 654fa9ecdSOlivier Giroux// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 754fa9ecdSOlivier Giroux// 854fa9ecdSOlivier Giroux//===----------------------------------------------------------------------===// 954fa9ecdSOlivier Giroux 1054fa9ecdSOlivier Giroux#ifndef _LIBCPP_LATCH 1154fa9ecdSOlivier Giroux#define _LIBCPP_LATCH 1254fa9ecdSOlivier Giroux 1354fa9ecdSOlivier Giroux/* 1454fa9ecdSOlivier Giroux latch synopsis 1554fa9ecdSOlivier Giroux 1654fa9ecdSOlivier Girouxnamespace std 1754fa9ecdSOlivier Giroux{ 1854fa9ecdSOlivier Giroux 1954fa9ecdSOlivier Giroux class latch 2054fa9ecdSOlivier Giroux { 2154fa9ecdSOlivier Giroux public: 22e2279c23SMarek Kurdej static constexpr ptrdiff_t max() noexcept; 23e2279c23SMarek Kurdej 2454fa9ecdSOlivier Giroux constexpr explicit latch(ptrdiff_t __expected); 2554fa9ecdSOlivier Giroux ~latch(); 2654fa9ecdSOlivier Giroux 2754fa9ecdSOlivier Giroux latch(const latch&) = delete; 2854fa9ecdSOlivier Giroux latch& operator=(const latch&) = delete; 2954fa9ecdSOlivier Giroux 3054fa9ecdSOlivier Giroux void count_down(ptrdiff_t __update = 1); 3154fa9ecdSOlivier Giroux bool try_wait() const noexcept; 3254fa9ecdSOlivier Giroux void wait() const; 3354fa9ecdSOlivier Giroux void arrive_and_wait(ptrdiff_t __update = 1); 3454fa9ecdSOlivier Giroux 3554fa9ecdSOlivier Giroux private: 3654fa9ecdSOlivier Giroux ptrdiff_t __counter; // exposition only 3754fa9ecdSOlivier Giroux }; 3854fa9ecdSOlivier Giroux 3954fa9ecdSOlivier Giroux} 4054fa9ecdSOlivier Giroux 4154fa9ecdSOlivier Giroux*/ 4254fa9ecdSOlivier Giroux 43385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler 442eadbc86SLouis Dionne#include <__availability> 45bfbd73f8SArthur O'Dwyer#include <__config> 4654fa9ecdSOlivier Giroux#include <atomic> 47*643df8faSLouis Dionne#include <limits> 48bd6e6846SMark de Wever#include <version> 4954fa9ecdSOlivier Giroux 5054fa9ecdSOlivier Giroux#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 5154fa9ecdSOlivier Giroux# pragma GCC system_header 5254fa9ecdSOlivier Giroux#endif 5354fa9ecdSOlivier Giroux 5454fa9ecdSOlivier Giroux#ifdef _LIBCPP_HAS_NO_THREADS 551c4b31c3SLouis Dionne# error "<latch> is not supported since libc++ has been configured without support for threads." 5654fa9ecdSOlivier Giroux#endif 5754fa9ecdSOlivier Giroux 58d4303307SArthur O'Dwyer_LIBCPP_PUSH_MACROS 59d4303307SArthur O'Dwyer#include <__undef_macros> 60d4303307SArthur O'Dwyer 61ab41129bSLouis Dionne#if _LIBCPP_STD_VER >= 14 6254fa9ecdSOlivier Giroux 6354fa9ecdSOlivier Giroux_LIBCPP_BEGIN_NAMESPACE_STD 6454fa9ecdSOlivier Giroux 6554fa9ecdSOlivier Girouxclass latch 6654fa9ecdSOlivier Giroux{ 6754fa9ecdSOlivier Giroux __atomic_base<ptrdiff_t> __a; 6854fa9ecdSOlivier Giroux 6954fa9ecdSOlivier Girouxpublic: 7054fa9ecdSOlivier Giroux static constexpr ptrdiff_t max() noexcept { 7154fa9ecdSOlivier Giroux return numeric_limits<ptrdiff_t>::max(); 7254fa9ecdSOlivier Giroux } 7354fa9ecdSOlivier Giroux 7454fa9ecdSOlivier Giroux inline _LIBCPP_INLINE_VISIBILITY 7554fa9ecdSOlivier Giroux constexpr explicit latch(ptrdiff_t __expected) : __a(__expected) { } 7654fa9ecdSOlivier Giroux 7754fa9ecdSOlivier Giroux ~latch() = default; 7854fa9ecdSOlivier Giroux latch(const latch&) = delete; 7954fa9ecdSOlivier Giroux latch& operator=(const latch&) = delete; 8054fa9ecdSOlivier Giroux 8146c38761SLouis Dionne inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 8254fa9ecdSOlivier Giroux void count_down(ptrdiff_t __update = 1) 8354fa9ecdSOlivier Giroux { 8454fa9ecdSOlivier Giroux auto const __old = __a.fetch_sub(__update, memory_order_release); 8554fa9ecdSOlivier Giroux if(__old == __update) 8654fa9ecdSOlivier Giroux __a.notify_all(); 8754fa9ecdSOlivier Giroux } 8854fa9ecdSOlivier Giroux inline _LIBCPP_INLINE_VISIBILITY 8954fa9ecdSOlivier Giroux bool try_wait() const noexcept 9054fa9ecdSOlivier Giroux { 9154fa9ecdSOlivier Giroux return 0 == __a.load(memory_order_acquire); 9254fa9ecdSOlivier Giroux } 9346c38761SLouis Dionne inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 9454fa9ecdSOlivier Giroux void wait() const 9554fa9ecdSOlivier Giroux { 96e39095a3SLouis Dionne __cxx_atomic_wait(&__a.__a_, [&]() -> bool { 9754fa9ecdSOlivier Giroux return try_wait(); 98e39095a3SLouis Dionne }); 9954fa9ecdSOlivier Giroux } 10046c38761SLouis Dionne inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 10154fa9ecdSOlivier Giroux void arrive_and_wait(ptrdiff_t __update = 1) 10254fa9ecdSOlivier Giroux { 10354fa9ecdSOlivier Giroux count_down(__update); 10454fa9ecdSOlivier Giroux wait(); 10554fa9ecdSOlivier Giroux } 10654fa9ecdSOlivier Giroux}; 10754fa9ecdSOlivier Giroux 10854fa9ecdSOlivier Giroux_LIBCPP_END_NAMESPACE_STD 10954fa9ecdSOlivier Giroux 110ab41129bSLouis Dionne#endif // _LIBCPP_STD_VER >= 14 111ab41129bSLouis Dionne 112d4303307SArthur O'Dwyer_LIBCPP_POP_MACROS 113d4303307SArthur O'Dwyer 11454fa9ecdSOlivier Giroux#endif //_LIBCPP_LATCH 115