115 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| // -*- C++ -*-
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #ifndef _LIBCPP_LATCH
 | |
| #define _LIBCPP_LATCH
 | |
| 
 | |
| /*
 | |
|     latch synopsis
 | |
| 
 | |
| namespace std
 | |
| {
 | |
| 
 | |
|   class latch
 | |
|   {
 | |
|   public:
 | |
|     static constexpr ptrdiff_t max() noexcept;
 | |
| 
 | |
|     constexpr explicit latch(ptrdiff_t __expected);
 | |
|     ~latch();
 | |
| 
 | |
|     latch(const latch&) = delete;
 | |
|     latch& operator=(const latch&) = delete;
 | |
| 
 | |
|     void count_down(ptrdiff_t __update = 1);
 | |
|     bool try_wait() const noexcept;
 | |
|     void wait() const;
 | |
|     void arrive_and_wait(ptrdiff_t __update = 1);
 | |
| 
 | |
|   private:
 | |
|     ptrdiff_t __counter; // exposition only
 | |
|   };
 | |
| 
 | |
| }
 | |
| 
 | |
| */
 | |
| 
 | |
| #include <__assert> // all public C++ headers provide the assertion handler
 | |
| #include <__availability>
 | |
| #include <__config>
 | |
| #include <atomic>
 | |
| #include <limits>
 | |
| #include <version>
 | |
| 
 | |
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 | |
| #  pragma GCC system_header
 | |
| #endif
 | |
| 
 | |
| #ifdef _LIBCPP_HAS_NO_THREADS
 | |
| # error "<latch> is not supported since libc++ has been configured without support for threads."
 | |
| #endif
 | |
| 
 | |
| _LIBCPP_PUSH_MACROS
 | |
| #include <__undef_macros>
 | |
| 
 | |
| #if _LIBCPP_STD_VER >= 14
 | |
| 
 | |
| _LIBCPP_BEGIN_NAMESPACE_STD
 | |
| 
 | |
| class latch
 | |
| {
 | |
|     __atomic_base<ptrdiff_t> __a;
 | |
| 
 | |
| public:
 | |
|     static constexpr ptrdiff_t max() noexcept {
 | |
|         return numeric_limits<ptrdiff_t>::max();
 | |
|     }
 | |
| 
 | |
|     inline _LIBCPP_INLINE_VISIBILITY
 | |
|     constexpr explicit latch(ptrdiff_t __expected) : __a(__expected) { }
 | |
| 
 | |
|     ~latch() = default;
 | |
|     latch(const latch&) = delete;
 | |
|     latch& operator=(const latch&) = delete;
 | |
| 
 | |
|     inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
 | |
|     void count_down(ptrdiff_t __update = 1)
 | |
|     {
 | |
|         auto const __old = __a.fetch_sub(__update, memory_order_release);
 | |
|         if(__old == __update)
 | |
|             __a.notify_all();
 | |
|     }
 | |
|     inline _LIBCPP_INLINE_VISIBILITY
 | |
|     bool try_wait() const noexcept
 | |
|     {
 | |
|         return 0 == __a.load(memory_order_acquire);
 | |
|     }
 | |
|     inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
 | |
|     void wait() const
 | |
|     {
 | |
|         __cxx_atomic_wait(&__a.__a_, [&]() -> bool {
 | |
|             return try_wait();
 | |
|         });
 | |
|     }
 | |
|     inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
 | |
|     void arrive_and_wait(ptrdiff_t __update = 1)
 | |
|     {
 | |
|         count_down(__update);
 | |
|         wait();
 | |
|     }
 | |
| };
 | |
| 
 | |
| _LIBCPP_END_NAMESPACE_STD
 | |
| 
 | |
| #endif // _LIBCPP_STD_VER >= 14
 | |
| 
 | |
| _LIBCPP_POP_MACROS
 | |
| 
 | |
| #endif //_LIBCPP_LATCH
 |