15ffd83dbSDimitry Andric// -*- C++ -*- 2349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 35ffd83dbSDimitry Andric// 45ffd83dbSDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 55ffd83dbSDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 65ffd83dbSDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 75ffd83dbSDimitry Andric// 85ffd83dbSDimitry Andric//===----------------------------------------------------------------------===// 95ffd83dbSDimitry Andric 105ffd83dbSDimitry Andric#ifndef _LIBCPP_LATCH 115ffd83dbSDimitry Andric#define _LIBCPP_LATCH 125ffd83dbSDimitry Andric 135ffd83dbSDimitry Andric/* 145ffd83dbSDimitry Andric latch synopsis 155ffd83dbSDimitry Andric 165ffd83dbSDimitry Andricnamespace std 175ffd83dbSDimitry Andric{ 185ffd83dbSDimitry Andric 195ffd83dbSDimitry Andric class latch 205ffd83dbSDimitry Andric { 215ffd83dbSDimitry Andric public: 22e8d8bef9SDimitry Andric static constexpr ptrdiff_t max() noexcept; 23e8d8bef9SDimitry Andric 245ffd83dbSDimitry Andric constexpr explicit latch(ptrdiff_t __expected); 255ffd83dbSDimitry Andric ~latch(); 265ffd83dbSDimitry Andric 275ffd83dbSDimitry Andric latch(const latch&) = delete; 285ffd83dbSDimitry Andric latch& operator=(const latch&) = delete; 295ffd83dbSDimitry Andric 305ffd83dbSDimitry Andric void count_down(ptrdiff_t __update = 1); 315ffd83dbSDimitry Andric bool try_wait() const noexcept; 325ffd83dbSDimitry Andric void wait() const; 335ffd83dbSDimitry Andric void arrive_and_wait(ptrdiff_t __update = 1); 345ffd83dbSDimitry Andric 355ffd83dbSDimitry Andric private: 365ffd83dbSDimitry Andric ptrdiff_t __counter; // exposition only 375ffd83dbSDimitry Andric }; 385ffd83dbSDimitry Andric 395ffd83dbSDimitry Andric} 405ffd83dbSDimitry Andric 415ffd83dbSDimitry Andric*/ 425ffd83dbSDimitry Andric 43e8d8bef9SDimitry Andric#include <__availability> 44fe6060f1SDimitry Andric#include <__config> 455ffd83dbSDimitry Andric#include <atomic> 46*04eeddc0SDimitry Andric#include <version> 475ffd83dbSDimitry Andric 485ffd83dbSDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 495ffd83dbSDimitry Andric#pragma GCC system_header 505ffd83dbSDimitry Andric#endif 515ffd83dbSDimitry Andric 525ffd83dbSDimitry Andric#ifdef _LIBCPP_HAS_NO_THREADS 535ffd83dbSDimitry Andric# error <latch> is not supported on this single threaded system 545ffd83dbSDimitry Andric#endif 555ffd83dbSDimitry Andric 56e8d8bef9SDimitry Andric_LIBCPP_PUSH_MACROS 57e8d8bef9SDimitry Andric#include <__undef_macros> 58e8d8bef9SDimitry Andric 595ffd83dbSDimitry Andric#if _LIBCPP_STD_VER >= 14 605ffd83dbSDimitry Andric 615ffd83dbSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 625ffd83dbSDimitry Andric 635ffd83dbSDimitry Andricclass latch 645ffd83dbSDimitry Andric{ 655ffd83dbSDimitry Andric __atomic_base<ptrdiff_t> __a; 665ffd83dbSDimitry Andric 675ffd83dbSDimitry Andricpublic: 685ffd83dbSDimitry Andric static constexpr ptrdiff_t max() noexcept { 695ffd83dbSDimitry Andric return numeric_limits<ptrdiff_t>::max(); 705ffd83dbSDimitry Andric } 715ffd83dbSDimitry Andric 725ffd83dbSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 735ffd83dbSDimitry Andric constexpr explicit latch(ptrdiff_t __expected) : __a(__expected) { } 745ffd83dbSDimitry Andric 755ffd83dbSDimitry Andric ~latch() = default; 765ffd83dbSDimitry Andric latch(const latch&) = delete; 775ffd83dbSDimitry Andric latch& operator=(const latch&) = delete; 785ffd83dbSDimitry Andric 795ffd83dbSDimitry Andric inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 805ffd83dbSDimitry Andric void count_down(ptrdiff_t __update = 1) 815ffd83dbSDimitry Andric { 825ffd83dbSDimitry Andric auto const __old = __a.fetch_sub(__update, memory_order_release); 835ffd83dbSDimitry Andric if(__old == __update) 845ffd83dbSDimitry Andric __a.notify_all(); 855ffd83dbSDimitry Andric } 865ffd83dbSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 875ffd83dbSDimitry Andric bool try_wait() const noexcept 885ffd83dbSDimitry Andric { 895ffd83dbSDimitry Andric return 0 == __a.load(memory_order_acquire); 905ffd83dbSDimitry Andric } 915ffd83dbSDimitry Andric inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 925ffd83dbSDimitry Andric void wait() const 935ffd83dbSDimitry Andric { 945ffd83dbSDimitry Andric auto const __test_fn = [=]() -> bool { 955ffd83dbSDimitry Andric return try_wait(); 965ffd83dbSDimitry Andric }; 975ffd83dbSDimitry Andric __cxx_atomic_wait(&__a.__a_, __test_fn); 985ffd83dbSDimitry Andric } 995ffd83dbSDimitry Andric inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY 1005ffd83dbSDimitry Andric void arrive_and_wait(ptrdiff_t __update = 1) 1015ffd83dbSDimitry Andric { 1025ffd83dbSDimitry Andric count_down(__update); 1035ffd83dbSDimitry Andric wait(); 1045ffd83dbSDimitry Andric } 1055ffd83dbSDimitry Andric}; 1065ffd83dbSDimitry Andric 1075ffd83dbSDimitry Andric_LIBCPP_END_NAMESPACE_STD 1085ffd83dbSDimitry Andric 1095ffd83dbSDimitry Andric#endif // _LIBCPP_STD_VER >= 14 1105ffd83dbSDimitry Andric 111e8d8bef9SDimitry Andric_LIBCPP_POP_MACROS 112e8d8bef9SDimitry Andric 1135ffd83dbSDimitry Andric#endif //_LIBCPP_LATCH 114