xref: /llvm-project-15.0.7/libcxx/include/latch (revision a852cf66)
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