xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/std/latch (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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