1*b1e83836Smrg// <latch> -*- C++ -*- 2*b1e83836Smrg 3*b1e83836Smrg// Copyright (C) 2020-2022 Free Software Foundation, Inc. 4*b1e83836Smrg// 5*b1e83836Smrg// This file is part of the GNU ISO C++ Library. This library is free 6*b1e83836Smrg// software; you can redistribute it and/or modify it under the 7*b1e83836Smrg// terms of the GNU General Public License as published by the 8*b1e83836Smrg// Free Software Foundation; either version 3, or (at your option) 9*b1e83836Smrg// any later version. 10*b1e83836Smrg 11*b1e83836Smrg// This library is distributed in the hope that it will be useful, 12*b1e83836Smrg// but WITHOUT ANY WARRANTY; without even the implied warranty of 13*b1e83836Smrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*b1e83836Smrg// GNU General Public License for more details. 15*b1e83836Smrg 16*b1e83836Smrg// Under Section 7 of GPL version 3, you are granted additional 17*b1e83836Smrg// permissions described in the GCC Runtime Library Exception, version 18*b1e83836Smrg// 3.1, as published by the Free Software Foundation. 19*b1e83836Smrg 20*b1e83836Smrg// You should have received a copy of the GNU General Public License and 21*b1e83836Smrg// a copy of the GCC Runtime Library Exception along with this program; 22*b1e83836Smrg// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*b1e83836Smrg// <http://www.gnu.org/licenses/>. 24*b1e83836Smrg 25*b1e83836Smrg/** @file include/latch 26*b1e83836Smrg * This is a Standard C++ Library header. 27*b1e83836Smrg */ 28*b1e83836Smrg 29*b1e83836Smrg#ifndef _GLIBCXX_LATCH 30*b1e83836Smrg#define _GLIBCXX_LATCH 1 31*b1e83836Smrg 32*b1e83836Smrg#pragma GCC system_header 33*b1e83836Smrg 34*b1e83836Smrg#if __cplusplus > 201703L 35*b1e83836Smrg 36*b1e83836Smrg#include <bits/atomic_base.h> 37*b1e83836Smrg#include <ext/numeric_traits.h> 38*b1e83836Smrg 39*b1e83836Smrg#if __cpp_lib_atomic_wait 40*b1e83836Smrgnamespace std _GLIBCXX_VISIBILITY(default) 41*b1e83836Smrg{ 42*b1e83836Smrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 43*b1e83836Smrg 44*b1e83836Smrg#define __cpp_lib_latch 201907L 45*b1e83836Smrg 46*b1e83836Smrg class latch 47*b1e83836Smrg { 48*b1e83836Smrg public: 49*b1e83836Smrg static constexpr ptrdiff_t 50*b1e83836Smrg max() noexcept 51*b1e83836Smrg { return __gnu_cxx::__int_traits<__detail::__platform_wait_t>::__max; } 52*b1e83836Smrg 53*b1e83836Smrg constexpr explicit latch(ptrdiff_t __expected) noexcept 54*b1e83836Smrg : _M_a(__expected) { } 55*b1e83836Smrg 56*b1e83836Smrg ~latch() = default; 57*b1e83836Smrg latch(const latch&) = delete; 58*b1e83836Smrg latch& operator=(const latch&) = delete; 59*b1e83836Smrg 60*b1e83836Smrg _GLIBCXX_ALWAYS_INLINE void 61*b1e83836Smrg count_down(ptrdiff_t __update = 1) 62*b1e83836Smrg { 63*b1e83836Smrg auto const __old = __atomic_impl::fetch_sub(&_M_a, 64*b1e83836Smrg __update, memory_order::release); 65*b1e83836Smrg if (__old == __update) 66*b1e83836Smrg __atomic_impl::notify_all(&_M_a); 67*b1e83836Smrg } 68*b1e83836Smrg 69*b1e83836Smrg _GLIBCXX_ALWAYS_INLINE bool 70*b1e83836Smrg try_wait() const noexcept 71*b1e83836Smrg { return __atomic_impl::load(&_M_a, memory_order::acquire) == 0; } 72*b1e83836Smrg 73*b1e83836Smrg _GLIBCXX_ALWAYS_INLINE void 74*b1e83836Smrg wait() const noexcept 75*b1e83836Smrg { 76*b1e83836Smrg auto const __pred = [this] { return this->try_wait(); }; 77*b1e83836Smrg std::__atomic_wait_address(&_M_a, __pred); 78*b1e83836Smrg } 79*b1e83836Smrg 80*b1e83836Smrg _GLIBCXX_ALWAYS_INLINE void 81*b1e83836Smrg arrive_and_wait(ptrdiff_t __update = 1) noexcept 82*b1e83836Smrg { 83*b1e83836Smrg count_down(__update); 84*b1e83836Smrg wait(); 85*b1e83836Smrg } 86*b1e83836Smrg 87*b1e83836Smrg private: 88*b1e83836Smrg alignas(__alignof__(__detail::__platform_wait_t)) __detail::__platform_wait_t _M_a; 89*b1e83836Smrg }; 90*b1e83836Smrg_GLIBCXX_END_NAMESPACE_VERSION 91*b1e83836Smrg} // namespace 92*b1e83836Smrg#endif // __cpp_lib_atomic_wait 93*b1e83836Smrg#endif // __cplusplus > 201703L 94*b1e83836Smrg#endif // _GLIBCXX_LATCH 95