xref: /llvm-project-15.0.7/libcxx/include/latch (revision 643df8fa)
154fa9ecdSOlivier Giroux// -*- C++ -*-
2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===//
354fa9ecdSOlivier Giroux//
454fa9ecdSOlivier Giroux// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
554fa9ecdSOlivier Giroux// See https://llvm.org/LICENSE.txt for license information.
654fa9ecdSOlivier Giroux// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
754fa9ecdSOlivier Giroux//
854fa9ecdSOlivier Giroux//===----------------------------------------------------------------------===//
954fa9ecdSOlivier Giroux
1054fa9ecdSOlivier Giroux#ifndef _LIBCPP_LATCH
1154fa9ecdSOlivier Giroux#define _LIBCPP_LATCH
1254fa9ecdSOlivier Giroux
1354fa9ecdSOlivier Giroux/*
1454fa9ecdSOlivier Giroux    latch synopsis
1554fa9ecdSOlivier Giroux
1654fa9ecdSOlivier Girouxnamespace std
1754fa9ecdSOlivier Giroux{
1854fa9ecdSOlivier Giroux
1954fa9ecdSOlivier Giroux  class latch
2054fa9ecdSOlivier Giroux  {
2154fa9ecdSOlivier Giroux  public:
22e2279c23SMarek Kurdej    static constexpr ptrdiff_t max() noexcept;
23e2279c23SMarek Kurdej
2454fa9ecdSOlivier Giroux    constexpr explicit latch(ptrdiff_t __expected);
2554fa9ecdSOlivier Giroux    ~latch();
2654fa9ecdSOlivier Giroux
2754fa9ecdSOlivier Giroux    latch(const latch&) = delete;
2854fa9ecdSOlivier Giroux    latch& operator=(const latch&) = delete;
2954fa9ecdSOlivier Giroux
3054fa9ecdSOlivier Giroux    void count_down(ptrdiff_t __update = 1);
3154fa9ecdSOlivier Giroux    bool try_wait() const noexcept;
3254fa9ecdSOlivier Giroux    void wait() const;
3354fa9ecdSOlivier Giroux    void arrive_and_wait(ptrdiff_t __update = 1);
3454fa9ecdSOlivier Giroux
3554fa9ecdSOlivier Giroux  private:
3654fa9ecdSOlivier Giroux    ptrdiff_t __counter; // exposition only
3754fa9ecdSOlivier Giroux  };
3854fa9ecdSOlivier Giroux
3954fa9ecdSOlivier Giroux}
4054fa9ecdSOlivier Giroux
4154fa9ecdSOlivier Giroux*/
4254fa9ecdSOlivier Giroux
43385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler
442eadbc86SLouis Dionne#include <__availability>
45bfbd73f8SArthur O'Dwyer#include <__config>
4654fa9ecdSOlivier Giroux#include <atomic>
47*643df8faSLouis Dionne#include <limits>
48bd6e6846SMark de Wever#include <version>
4954fa9ecdSOlivier Giroux
5054fa9ecdSOlivier Giroux#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
5154fa9ecdSOlivier Giroux#  pragma GCC system_header
5254fa9ecdSOlivier Giroux#endif
5354fa9ecdSOlivier Giroux
5454fa9ecdSOlivier Giroux#ifdef _LIBCPP_HAS_NO_THREADS
551c4b31c3SLouis Dionne# error "<latch> is not supported since libc++ has been configured without support for threads."
5654fa9ecdSOlivier Giroux#endif
5754fa9ecdSOlivier Giroux
58d4303307SArthur O'Dwyer_LIBCPP_PUSH_MACROS
59d4303307SArthur O'Dwyer#include <__undef_macros>
60d4303307SArthur O'Dwyer
61ab41129bSLouis Dionne#if _LIBCPP_STD_VER >= 14
6254fa9ecdSOlivier Giroux
6354fa9ecdSOlivier Giroux_LIBCPP_BEGIN_NAMESPACE_STD
6454fa9ecdSOlivier Giroux
6554fa9ecdSOlivier Girouxclass latch
6654fa9ecdSOlivier Giroux{
6754fa9ecdSOlivier Giroux    __atomic_base<ptrdiff_t> __a;
6854fa9ecdSOlivier Giroux
6954fa9ecdSOlivier Girouxpublic:
7054fa9ecdSOlivier Giroux    static constexpr ptrdiff_t max() noexcept {
7154fa9ecdSOlivier Giroux        return numeric_limits<ptrdiff_t>::max();
7254fa9ecdSOlivier Giroux    }
7354fa9ecdSOlivier Giroux
7454fa9ecdSOlivier Giroux    inline _LIBCPP_INLINE_VISIBILITY
7554fa9ecdSOlivier Giroux    constexpr explicit latch(ptrdiff_t __expected) : __a(__expected) { }
7654fa9ecdSOlivier Giroux
7754fa9ecdSOlivier Giroux    ~latch() = default;
7854fa9ecdSOlivier Giroux    latch(const latch&) = delete;
7954fa9ecdSOlivier Giroux    latch& operator=(const latch&) = delete;
8054fa9ecdSOlivier Giroux
8146c38761SLouis Dionne    inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
8254fa9ecdSOlivier Giroux    void count_down(ptrdiff_t __update = 1)
8354fa9ecdSOlivier Giroux    {
8454fa9ecdSOlivier Giroux        auto const __old = __a.fetch_sub(__update, memory_order_release);
8554fa9ecdSOlivier Giroux        if(__old == __update)
8654fa9ecdSOlivier Giroux            __a.notify_all();
8754fa9ecdSOlivier Giroux    }
8854fa9ecdSOlivier Giroux    inline _LIBCPP_INLINE_VISIBILITY
8954fa9ecdSOlivier Giroux    bool try_wait() const noexcept
9054fa9ecdSOlivier Giroux    {
9154fa9ecdSOlivier Giroux        return 0 == __a.load(memory_order_acquire);
9254fa9ecdSOlivier Giroux    }
9346c38761SLouis Dionne    inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
9454fa9ecdSOlivier Giroux    void wait() const
9554fa9ecdSOlivier Giroux    {
96e39095a3SLouis Dionne        __cxx_atomic_wait(&__a.__a_, [&]() -> bool {
9754fa9ecdSOlivier Giroux            return try_wait();
98e39095a3SLouis Dionne        });
9954fa9ecdSOlivier Giroux    }
10046c38761SLouis Dionne    inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
10154fa9ecdSOlivier Giroux    void arrive_and_wait(ptrdiff_t __update = 1)
10254fa9ecdSOlivier Giroux    {
10354fa9ecdSOlivier Giroux        count_down(__update);
10454fa9ecdSOlivier Giroux        wait();
10554fa9ecdSOlivier Giroux    }
10654fa9ecdSOlivier Giroux};
10754fa9ecdSOlivier Giroux
10854fa9ecdSOlivier Giroux_LIBCPP_END_NAMESPACE_STD
10954fa9ecdSOlivier Giroux
110ab41129bSLouis Dionne#endif // _LIBCPP_STD_VER >= 14
111ab41129bSLouis Dionne
112d4303307SArthur O'Dwyer_LIBCPP_POP_MACROS
113d4303307SArthur O'Dwyer
11454fa9ecdSOlivier Giroux#endif //_LIBCPP_LATCH
115