blob: 7c8b2f52205bcc8fcc38dbaa9e96ddf38a4e8f4f [file] [log] [blame]
Olivier Giroux161e6e82020-02-18 09:58:34 -05001// -*- 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 <atomic>
43
44#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
45#pragma GCC system_header
46#endif
47
48#ifdef _LIBCPP_HAS_NO_THREADS
49# error <latch> is not supported on this single threaded system
50#endif
51
52#if _LIBCPP_STD_VER < 14
53# error <latch> requires C++14 or later
54#endif
55
56_LIBCPP_BEGIN_NAMESPACE_STD
57
58class latch
59{
60 __atomic_base<ptrdiff_t> __a;
61
62public:
63 static constexpr ptrdiff_t max() noexcept {
64 return numeric_limits<ptrdiff_t>::max();
65 }
66
67 inline _LIBCPP_INLINE_VISIBILITY
68 constexpr explicit latch(ptrdiff_t __expected) : __a(__expected) { }
69
70 ~latch() = default;
71 latch(const latch&) = delete;
72 latch& operator=(const latch&) = delete;
73
74 inline _LIBCPP_INLINE_VISIBILITY
75 void count_down(ptrdiff_t __update = 1)
76 {
77 auto const __old = __a.fetch_sub(__update, memory_order_release);
78 if(__old == __update)
79 __a.notify_all();
80 }
81 inline _LIBCPP_INLINE_VISIBILITY
82 bool try_wait() const noexcept
83 {
84 return 0 == __a.load(memory_order_acquire);
85 }
86 inline _LIBCPP_INLINE_VISIBILITY
87 void wait() const
88 {
89 auto const __test_fn = [=]() -> bool {
90 return try_wait();
91 };
92 __cxx_atomic_wait(&__a.__a_, __test_fn);
93 }
94 inline _LIBCPP_INLINE_VISIBILITY
95 void arrive_and_wait(ptrdiff_t __update = 1)
96 {
97 count_down(__update);
98 wait();
99 }
100};
101
102_LIBCPP_END_NAMESPACE_STD
103
104#endif //_LIBCPP_LATCH