blob: b338f091316c74608e9e98849ed471af7bea11dd [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>
Louis Dionne73912b22020-11-04 15:01:25 -050042#include <__availability>
Olivier Giroux161e6e82020-02-18 09:58:34 -050043#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
Arthur O'Dwyer2422fa22020-12-02 18:55:01 -050053_LIBCPP_PUSH_MACROS
54#include <__undef_macros>
55
Louis Dionne1ab95312020-02-24 18:12:44 -050056#if _LIBCPP_STD_VER >= 14
Olivier Giroux161e6e82020-02-18 09:58:34 -050057
58_LIBCPP_BEGIN_NAMESPACE_STD
59
60class latch
61{
62 __atomic_base<ptrdiff_t> __a;
63
64public:
65 static constexpr ptrdiff_t max() noexcept {
66 return numeric_limits<ptrdiff_t>::max();
67 }
68
69 inline _LIBCPP_INLINE_VISIBILITY
70 constexpr explicit latch(ptrdiff_t __expected) : __a(__expected) { }
71
72 ~latch() = default;
73 latch(const latch&) = delete;
74 latch& operator=(const latch&) = delete;
75
Louis Dionne3dde4ab2020-02-24 10:09:29 -050076 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
Olivier Giroux161e6e82020-02-18 09:58:34 -050077 void count_down(ptrdiff_t __update = 1)
78 {
79 auto const __old = __a.fetch_sub(__update, memory_order_release);
80 if(__old == __update)
81 __a.notify_all();
82 }
83 inline _LIBCPP_INLINE_VISIBILITY
84 bool try_wait() const noexcept
85 {
86 return 0 == __a.load(memory_order_acquire);
87 }
Louis Dionne3dde4ab2020-02-24 10:09:29 -050088 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
Olivier Giroux161e6e82020-02-18 09:58:34 -050089 void wait() const
90 {
91 auto const __test_fn = [=]() -> bool {
92 return try_wait();
93 };
94 __cxx_atomic_wait(&__a.__a_, __test_fn);
95 }
Louis Dionne3dde4ab2020-02-24 10:09:29 -050096 inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
Olivier Giroux161e6e82020-02-18 09:58:34 -050097 void arrive_and_wait(ptrdiff_t __update = 1)
98 {
99 count_down(__update);
100 wait();
101 }
102};
103
104_LIBCPP_END_NAMESPACE_STD
105
Louis Dionne1ab95312020-02-24 18:12:44 -0500106#endif // _LIBCPP_STD_VER >= 14
107
Arthur O'Dwyer2422fa22020-12-02 18:55:01 -0500108_LIBCPP_POP_MACROS
109
Olivier Giroux161e6e82020-02-18 09:58:34 -0500110#endif //_LIBCPP_LATCH