blob: e1e15190ae4a7e77619058b133120ec4afe9b967 [file] [log] [blame]
Olivier Giroux161e6e82020-02-18 09:58:34 -05001// -*- C++ -*-
Louis Dionne9bd93882021-11-17 16:25:01 -05002//===----------------------------------------------------------------------===//
Olivier Giroux161e6e82020-02-18 09:58:34 -05003//
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:
Marek Kurdej7f401b92020-12-06 15:36:18 +010022 static constexpr ptrdiff_t max() noexcept;
23
Olivier Giroux161e6e82020-02-18 09:58:34 -050024 constexpr explicit latch(ptrdiff_t __expected);
25 ~latch();
26
27 latch(const latch&) = delete;
28 latch& operator=(const latch&) = delete;
29
30 void count_down(ptrdiff_t __update = 1);
31 bool try_wait() const noexcept;
32 void wait() const;
33 void arrive_and_wait(ptrdiff_t __update = 1);
34
35 private:
36 ptrdiff_t __counter; // exposition only
37 };
38
39}
40
41*/
42
Louis Dionne73912b22020-11-04 15:01:25 -050043#include <__availability>
Arthur O'Dwyeref181602021-05-19 11:57:04 -040044#include <__config>
Olivier Giroux161e6e82020-02-18 09:58:34 -050045#include <atomic>
Mark de Weverce8f12c2021-12-22 18:14:14 +010046#include <version>
Olivier Giroux161e6e82020-02-18 09:58:34 -050047
48#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Arthur O'Dwyer6eeaa002022-02-01 20:16:40 -050049# pragma GCC system_header
Olivier Giroux161e6e82020-02-18 09:58:34 -050050#endif
51
52#ifdef _LIBCPP_HAS_NO_THREADS
53# error <latch> is not supported on this single threaded system
54#endif
55
Arthur O'Dwyer2422fa22020-12-02 18:55:01 -050056_LIBCPP_PUSH_MACROS
57#include <__undef_macros>
58
Louis Dionne1ab95312020-02-24 18:12:44 -050059#if _LIBCPP_STD_VER >= 14
Olivier Giroux161e6e82020-02-18 09:58:34 -050060
61_LIBCPP_BEGIN_NAMESPACE_STD
62
63class latch
64{
65 __atomic_base<ptrdiff_t> __a;
66
67public:
68 static constexpr ptrdiff_t max() noexcept {
69 return numeric_limits<ptrdiff_t>::max();
70 }
71
72 inline _LIBCPP_INLINE_VISIBILITY
73 constexpr explicit latch(ptrdiff_t __expected) : __a(__expected) { }
74
75 ~latch() = default;
76 latch(const latch&) = delete;
77 latch& operator=(const latch&) = delete;
78
Louis Dionne3dde4ab2020-02-24 10:09:29 -050079 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
Olivier Giroux161e6e82020-02-18 09:58:34 -050080 void count_down(ptrdiff_t __update = 1)
81 {
82 auto const __old = __a.fetch_sub(__update, memory_order_release);
83 if(__old == __update)
84 __a.notify_all();
85 }
86 inline _LIBCPP_INLINE_VISIBILITY
87 bool try_wait() const noexcept
88 {
89 return 0 == __a.load(memory_order_acquire);
90 }
Louis Dionne3dde4ab2020-02-24 10:09:29 -050091 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
Olivier Giroux161e6e82020-02-18 09:58:34 -050092 void wait() const
93 {
94 auto const __test_fn = [=]() -> bool {
95 return try_wait();
96 };
97 __cxx_atomic_wait(&__a.__a_, __test_fn);
98 }
Louis Dionne3dde4ab2020-02-24 10:09:29 -050099 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
Olivier Giroux161e6e82020-02-18 09:58:34 -0500100 void arrive_and_wait(ptrdiff_t __update = 1)
101 {
102 count_down(__update);
103 wait();
104 }
105};
106
107_LIBCPP_END_NAMESPACE_STD
108
Louis Dionne1ab95312020-02-24 18:12:44 -0500109#endif // _LIBCPP_STD_VER >= 14
110
Arthur O'Dwyer2422fa22020-12-02 18:55:01 -0500111_LIBCPP_POP_MACROS
112
Olivier Giroux161e6e82020-02-18 09:58:34 -0500113#endif //_LIBCPP_LATCH