| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,322 @@ | ||
| // -*- C++ -*- | ||
| //===--------------------------- barrier ----------------------------------===// | ||
| // | ||
| // 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_BARRIER | ||
| #define _LIBCPP_BARRIER | ||
|
|
||
| /* | ||
| barrier synopsis | ||
| namespace std | ||
| { | ||
| template<class CompletionFunction = see below> | ||
| class barrier | ||
| { | ||
| public: | ||
| using arrival_token = see below; | ||
| constexpr explicit barrier(ptrdiff_t phase_count, | ||
| CompletionFunction f = CompletionFunction()); | ||
| ~barrier(); | ||
| barrier(const barrier&) = delete; | ||
| barrier& operator=(const barrier&) = delete; | ||
| [[nodiscard]] arrival_token arrive(ptrdiff_t update = 1); | ||
| void wait(arrival_token&& arrival) const; | ||
| void arrive_and_wait(); | ||
| void arrive_and_drop(); | ||
| private: | ||
| CompletionFunction completion; // exposition only | ||
| }; | ||
| } | ||
| */ | ||
|
|
||
| #include <__config> | ||
| #include <atomic> | ||
| #ifndef _LIBCPP_HAS_NO_TREE_BARRIER | ||
| # include <memory> | ||
| #endif | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| #pragma GCC system_header | ||
| #endif | ||
|
|
||
| #ifdef _LIBCPP_HAS_NO_THREADS | ||
| # error <barrier> is not supported on this single threaded system | ||
| #endif | ||
|
|
||
| #if _LIBCPP_STD_VER < 14 | ||
| # error <barrier> requires C++14 or later | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| struct __empty_completion | ||
| { | ||
| inline _LIBCPP_INLINE_VISIBILITY | ||
| void operator()() noexcept | ||
| { | ||
| } | ||
| }; | ||
|
|
||
| #ifndef _LIBCPP_HAS_NO_TREE_BARRIER | ||
|
|
||
| /* | ||
| The default implementation of __barrier_base is a classic tree barrier. | ||
| It looks different from literature pseudocode for two main reasons: | ||
| 1. Threads that call into std::barrier functions do not provide indices, | ||
| so a numbering step is added before the actual barrier algorithm, | ||
| appearing as an N+1 round to the N rounds of the tree barrier. | ||
| 2. A great deal of attention has been paid to avoid cache line thrashing | ||
| by flattening the tree structure into cache-line sized arrays, that | ||
| are indexed in an efficient way. | ||
| */ | ||
|
|
||
| using __barrier_phase_t = uint8_t; | ||
|
|
||
| class __barrier_algorithm_base; | ||
|
|
||
| _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI | ||
| __barrier_algorithm_base* __construct_barrier_algorithm_base(ptrdiff_t& __expected); | ||
|
|
||
| _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI | ||
| bool __arrive_barrier_algorithm_base(__barrier_algorithm_base* __barrier, | ||
| __barrier_phase_t __old_phase); | ||
|
|
||
| _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI | ||
| void __destroy_barrier_algorithm_base(__barrier_algorithm_base* __barrier); | ||
|
|
||
| template<class _CompletionF> | ||
| class __barrier_base { | ||
|
|
||
| ptrdiff_t __expected; | ||
| unique_ptr<__barrier_algorithm_base, | ||
| decltype(&__destroy_barrier_algorithm_base)> __base; | ||
| __atomic_base<ptrdiff_t> __expected_adjustment; | ||
| _CompletionF __completion; | ||
| __atomic_base<__barrier_phase_t> __phase; | ||
|
|
||
| public: | ||
| using arrival_token = __barrier_phase_t; | ||
|
|
||
| static constexpr ptrdiff_t max() noexcept { | ||
| return numeric_limits<ptrdiff_t>::max(); | ||
| } | ||
|
|
||
| _LIBCPP_INLINE_VISIBILITY | ||
| __barrier_base(ptrdiff_t __expected, _CompletionF __completion = _CompletionF()) | ||
| : __expected(__expected), __base(__construct_barrier_algorithm_base(this->__expected), | ||
| &__destroy_barrier_algorithm_base), | ||
| __expected_adjustment(0), __completion(move(__completion)), __phase(0) | ||
| { | ||
| } | ||
| [[nodiscard]] _LIBCPP_INLINE_VISIBILITY | ||
| arrival_token arrive(ptrdiff_t update) | ||
| { | ||
| auto const __old_phase = __phase.load(memory_order_relaxed); | ||
| for(; update; --update) | ||
| if(__arrive_barrier_algorithm_base(__base.get(), __old_phase)) { | ||
| __completion(); | ||
| __expected += __expected_adjustment.load(memory_order_relaxed); | ||
| __expected_adjustment.store(0, memory_order_relaxed); | ||
| __phase.store(__old_phase + 2, memory_order_release); | ||
| __phase.notify_all(); | ||
| } | ||
| return __old_phase; | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| void wait(arrival_token&& __old_phase) const | ||
| { | ||
| auto const __test_fn = [=]() -> bool { | ||
| return __phase.load(memory_order_acquire) != __old_phase; | ||
| }; | ||
| __libcpp_thread_poll_with_backoff(__test_fn, __libcpp_timed_backoff_policy()); | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| void arrive_and_drop() | ||
| { | ||
| __expected_adjustment.fetch_sub(1, memory_order_relaxed); | ||
| (void)arrive(1); | ||
| } | ||
| }; | ||
|
|
||
| #else | ||
|
|
||
| /* | ||
| The alternative implementation of __barrier_base is a central barrier. | ||
| Two versions of this algorithm are provided: | ||
| 1. A fairly straightforward implementation of the litterature for the | ||
| general case where the completion function is not empty. | ||
| 2. An optimized implementation that exploits 2's complement arithmetic | ||
| and well-defined overflow in atomic arithmetic, to handle the phase | ||
| roll-over for free. | ||
| */ | ||
|
|
||
| template<class _CompletionF> | ||
| class __barrier_base { | ||
|
|
||
| __atomic_base<ptrdiff_t> __expected; | ||
| __atomic_base<ptrdiff_t> __arrived; | ||
| _CompletionF __completion; | ||
| __atomic_base<bool> __phase; | ||
| public: | ||
| using arrival_token = bool; | ||
|
|
||
| static constexpr ptrdiff_t max() noexcept { | ||
| return numeric_limits<ptrdiff_t>::max(); | ||
| } | ||
|
|
||
| _LIBCPP_INLINE_VISIBILITY | ||
| __barrier_base(ptrdiff_t __expected, _CompletionF __completion = _CompletionF()) | ||
| : __expected(__expected), __arrived(__expected), __completion(move(__completion)), __phase(false) | ||
| { | ||
| } | ||
| [[nodiscard]] _LIBCPP_INLINE_VISIBILITY | ||
| arrival_token arrive(ptrdiff_t update) | ||
| { | ||
| auto const __old_phase = __phase.load(memory_order_relaxed); | ||
| auto const __result = __arrived.fetch_sub(update, memory_order_acq_rel) - update; | ||
| auto const new_expected = __expected.load(memory_order_relaxed); | ||
| if(0 == __result) { | ||
| __completion(); | ||
| __arrived.store(new_expected, memory_order_relaxed); | ||
| __phase.store(!__old_phase, memory_order_release); | ||
| __phase.notify_all(); | ||
| } | ||
| return __old_phase; | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| void wait(arrival_token&& __old_phase) const | ||
| { | ||
| __phase.wait(__old_phase, memory_order_acquire); | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| void arrive_and_drop() | ||
| { | ||
| __expected.fetch_sub(1, memory_order_relaxed); | ||
| (void)arrive(1); | ||
| } | ||
| }; | ||
|
|
||
| template<> | ||
| class __barrier_base<__empty_completion> { | ||
|
|
||
| static constexpr uint64_t __expected_unit = 1ull; | ||
| static constexpr uint64_t __arrived_unit = 1ull << 32; | ||
| static constexpr uint64_t __expected_mask = __arrived_unit - 1; | ||
| static constexpr uint64_t __phase_bit = 1ull << 63; | ||
| static constexpr uint64_t __arrived_mask = (__phase_bit - 1) & ~__expected_mask; | ||
|
|
||
| __atomic_base<uint64_t> __phase_arrived_expected; | ||
|
|
||
| static _LIBCPP_INLINE_VISIBILITY | ||
| constexpr uint64_t __init(ptrdiff_t __count) _NOEXCEPT | ||
| { | ||
| return ((uint64_t(1u << 31) - __count) << 32) | ||
| | (uint64_t(1u << 31) - __count); | ||
| } | ||
|
|
||
| public: | ||
| using arrival_token = uint64_t; | ||
|
|
||
| static constexpr ptrdiff_t max() noexcept { | ||
| return ptrdiff_t(1u << 31) - 1; | ||
| } | ||
|
|
||
| _LIBCPP_INLINE_VISIBILITY | ||
| explicit inline __barrier_base(ptrdiff_t __count, __empty_completion = __empty_completion()) | ||
| : __phase_arrived_expected(__init(__count)) | ||
| { | ||
| } | ||
| [[nodiscard]] inline _LIBCPP_INLINE_VISIBILITY | ||
| arrival_token arrive(ptrdiff_t update) | ||
| { | ||
| auto const __inc = __arrived_unit * update; | ||
| auto const __old = __phase_arrived_expected.fetch_add(__inc, memory_order_acq_rel); | ||
| if((__old ^ (__old + __inc)) & __phase_bit) { | ||
| __phase_arrived_expected.fetch_add((__old & __expected_mask) << 32, memory_order_relaxed); | ||
| __phase_arrived_expected.notify_all(); | ||
| } | ||
| return __old & __phase_bit; | ||
| } | ||
| inline _LIBCPP_INLINE_VISIBILITY | ||
| void wait(arrival_token&& __phase) const | ||
| { | ||
| auto const __test_fn = [=]() -> bool { | ||
| uint64_t const __current = __phase_arrived_expected.load(memory_order_acquire); | ||
| return ((__current & __phase_bit) != __phase); | ||
| }; | ||
| __libcpp_thread_poll_with_backoff(__test_fn, __libcpp_timed_backoff_policy()); | ||
| } | ||
| inline _LIBCPP_INLINE_VISIBILITY | ||
| void arrive_and_drop() | ||
| { | ||
| __phase_arrived_expected.fetch_add(__expected_unit, memory_order_relaxed); | ||
| (void)arrive(1); | ||
| } | ||
| }; | ||
|
|
||
| #endif //_LIBCPP_HAS_NO_TREE_BARRIER | ||
|
|
||
| template<class _CompletionF = __empty_completion> | ||
| class barrier { | ||
|
|
||
| __barrier_base<_CompletionF> __b; | ||
| public: | ||
| using arrival_token = typename __barrier_base<_CompletionF>::arrival_token; | ||
|
|
||
| static constexpr ptrdiff_t max() noexcept { | ||
| return __barrier_base<_CompletionF>::max(); | ||
| } | ||
|
|
||
| _LIBCPP_INLINE_VISIBILITY | ||
| barrier(ptrdiff_t __count, _CompletionF __completion = _CompletionF()) | ||
| : __b(__count, std::move(__completion)) { | ||
| } | ||
|
|
||
| barrier(barrier const&) = delete; | ||
| barrier& operator=(barrier const&) = delete; | ||
|
|
||
| [[nodiscard]] _LIBCPP_INLINE_VISIBILITY | ||
| arrival_token arrive(ptrdiff_t update = 1) | ||
| { | ||
| return __b.arrive(update); | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| void wait(arrival_token&& __phase) const | ||
| { | ||
| __b.wait(std::move(__phase)); | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| void arrive_and_wait() | ||
| { | ||
| wait(arrive()); | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| void arrive_and_drop() | ||
| { | ||
| __b.arrive_and_drop(); | ||
| } | ||
| }; | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif //_LIBCPP_BARRIER |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| // -*- C++ -*- | ||
| //===--------------------------- latch -----------------------------------===// | ||
| // | ||
| // 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: | ||
| 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 <__config> | ||
| #include <atomic> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| #pragma GCC system_header | ||
| #endif | ||
|
|
||
| #ifdef _LIBCPP_HAS_NO_THREADS | ||
| # error <latch> is not supported on this single threaded system | ||
| #endif | ||
|
|
||
| #if _LIBCPP_STD_VER < 14 | ||
| # error <latch> requires C++14 or later | ||
| #endif | ||
|
|
||
| _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_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_INLINE_VISIBILITY | ||
| void wait() const | ||
| { | ||
| auto const __test_fn = [=]() -> bool { | ||
| return try_wait(); | ||
| }; | ||
| __cxx_atomic_wait(&__a.__a_, __test_fn); | ||
| } | ||
| inline _LIBCPP_INLINE_VISIBILITY | ||
| void arrive_and_wait(ptrdiff_t __update = 1) | ||
| { | ||
| count_down(__update); | ||
| wait(); | ||
| } | ||
| }; | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif //_LIBCPP_LATCH |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,233 @@ | ||
| // -*- C++ -*- | ||
| //===--------------------------- semaphore --------------------------------===// | ||
| // | ||
| // 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_SEMAPHORE | ||
| #define _LIBCPP_SEMAPHORE | ||
|
|
||
| /* | ||
| semaphore synopsis | ||
| namespace std { | ||
| template<ptrdiff_t least_max_value = implementation-defined> | ||
| class counting_semaphore | ||
| { | ||
| public: | ||
| static constexpr ptrdiff_t max() noexcept; | ||
| constexpr explicit counting_semaphore(ptrdiff_t desired); | ||
| ~counting_semaphore(); | ||
| counting_semaphore(const counting_semaphore&) = delete; | ||
| counting_semaphore& operator=(const counting_semaphore&) = delete; | ||
| void release(ptrdiff_t update = 1); | ||
| void acquire(); | ||
| bool try_acquire() noexcept; | ||
| template<class Rep, class Period> | ||
| bool try_acquire_for(const chrono::duration<Rep, Period>& rel_time); | ||
| template<class Clock, class Duration> | ||
| bool try_acquire_until(const chrono::time_point<Clock, Duration>& abs_time); | ||
| private: | ||
| ptrdiff_t counter; // exposition only | ||
| }; | ||
| using binary_semaphore = counting_semaphore<1>; | ||
| } | ||
| */ | ||
|
|
||
| #include <__config> | ||
| #include <__threading_support> | ||
| #include <atomic> | ||
| #include <cassert> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| #pragma GCC system_header | ||
| #endif | ||
|
|
||
| #ifdef _LIBCPP_HAS_NO_THREADS | ||
| # error <semaphore> is not supported on this single threaded system | ||
| #endif | ||
|
|
||
| #if _LIBCPP_STD_VER < 14 | ||
| # error <semaphore> is requires C++14 or later | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| /* | ||
| __atomic_semaphore_base is the general-case implementation, to be used for | ||
| user-requested least-max values that exceed the OS implementation support | ||
| (incl. when the OS has no support of its own) and for binary semaphores. | ||
| It is a typical Dijsktra semaphore algorithm over atomics, wait and notify | ||
| functions. It avoids contention against users' own use of those facilities. | ||
| */ | ||
|
|
||
| class __atomic_semaphore_base | ||
| { | ||
| __atomic_base<ptrdiff_t> __a; | ||
|
|
||
| public: | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| __atomic_semaphore_base(ptrdiff_t __count) : __a(__count) | ||
| { | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| void release(ptrdiff_t __update = 1) | ||
| { | ||
| if(0 < __a.fetch_add(__update, memory_order_release)) | ||
| ; | ||
| else if(__update > 1) | ||
| __a.notify_all(); | ||
| else | ||
| __a.notify_one(); | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| void acquire() | ||
| { | ||
| auto const __test_fn = [=]() -> bool { | ||
| auto __old = __a.load(memory_order_relaxed); | ||
| return (__old != 0) && __a.compare_exchange_strong(__old, __old - 1, memory_order_acquire, memory_order_relaxed); | ||
| }; | ||
| __cxx_atomic_wait(&__a.__a_, __test_fn); | ||
| } | ||
| template <class Rep, class Period> | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| bool try_acquire_for(chrono::duration<Rep, Period> const& __rel_time) | ||
| { | ||
| auto const __test_fn = [=]() -> bool { | ||
| auto __old = __a.load(memory_order_acquire); | ||
| while(1) { | ||
| if (__old == 0) | ||
| return false; | ||
| if(__a.compare_exchange_strong(__old, __old - 1, memory_order_acquire, memory_order_relaxed)) | ||
| return true; | ||
| } | ||
| }; | ||
| return __libcpp_thread_poll_with_backoff(__test_fn, __libcpp_timed_backoff_policy(), __rel_time); | ||
| } | ||
| }; | ||
|
|
||
| #ifndef _LIBCPP_NO_NATIVE_SEMAPHORES | ||
|
|
||
| /* | ||
| __platform_semaphore_base a simple wrapper for the OS semaphore type. That | ||
| is, every call is routed to the OS in the most direct manner possible. | ||
| */ | ||
|
|
||
| class __platform_semaphore_base | ||
| { | ||
| __libcpp_semaphore_t __semaphore; | ||
|
|
||
| public: | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| __platform_semaphore_base(ptrdiff_t __count) : | ||
| __semaphore() | ||
| { | ||
| __libcpp_semaphore_init(&__semaphore, __count); | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| ~__platform_semaphore_base() { | ||
| __libcpp_semaphore_destroy(&__semaphore); | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| void release(ptrdiff_t __update) | ||
| { | ||
| for(; __update; --__update) | ||
| __libcpp_semaphore_post(&__semaphore); | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| void acquire() | ||
| { | ||
| __libcpp_semaphore_wait(&__semaphore); | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| bool try_acquire_for(chrono::nanoseconds __rel_time) | ||
| { | ||
| return __libcpp_semaphore_wait_timed(&__semaphore, __rel_time); | ||
| } | ||
| }; | ||
|
|
||
| template<ptrdiff_t __least_max_value> | ||
| using __semaphore_base = | ||
| typename conditional<(__least_max_value > 1 && __least_max_value <= _LIBCPP_SEMAPHORE_MAX), | ||
| __platform_semaphore_base, | ||
| __atomic_semaphore_base>::type; | ||
|
|
||
| #else | ||
|
|
||
| template<ptrdiff_t __least_max_value> | ||
| using __semaphore_base = | ||
| __atomic_semaphore_base; | ||
|
|
||
| #endif //_LIBCPP_NO_NATIVE_SEMAPHORES | ||
|
|
||
| template<ptrdiff_t __least_max_value = _LIBCPP_SEMAPHORE_MAX> | ||
| class counting_semaphore | ||
| { | ||
| __semaphore_base<__least_max_value> __semaphore; | ||
|
|
||
| public: | ||
| static constexpr ptrdiff_t max() noexcept { | ||
| return __least_max_value; | ||
| } | ||
|
|
||
| _LIBCPP_INLINE_VISIBILITY | ||
| counting_semaphore(ptrdiff_t __count = 0) : __semaphore(__count) { } | ||
| ~counting_semaphore() = default; | ||
|
|
||
| counting_semaphore(const counting_semaphore&) = delete; | ||
| counting_semaphore& operator=(const counting_semaphore&) = delete; | ||
|
|
||
| _LIBCPP_INLINE_VISIBILITY | ||
| void release(ptrdiff_t __update = 1) | ||
| { | ||
| __semaphore.release(__update); | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| void acquire() | ||
| { | ||
| __semaphore.acquire(); | ||
| } | ||
| template<class Rep, class Period> | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| bool try_acquire_for(chrono::duration<Rep, Period> const& __rel_time) | ||
| { | ||
| return __semaphore.try_acquire_for(chrono::duration_cast<chrono::nanoseconds>(__rel_time)); | ||
| } | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| bool try_acquire() | ||
| { | ||
| return try_acquire_for(chrono::nanoseconds::zero()); | ||
| } | ||
| template <class Clock, class Duration> | ||
| _LIBCPP_INLINE_VISIBILITY | ||
| bool try_acquire_until(chrono::time_point<Clock, Duration> const& __abs_time) | ||
| { | ||
| auto const current = Clock::now(); | ||
| if(current >= __abs_time) | ||
| return try_acquire(); | ||
| else | ||
| return try_acquire_for(__abs_time - current); | ||
| } | ||
| }; | ||
|
|
||
| using binary_semaphore = counting_semaphore<1>; | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif //_LIBCPP_SEMAPHORE |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| //===------------------------- atomic.cpp ---------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <__config> | ||
| #ifndef _LIBCPP_HAS_NO_THREADS | ||
|
|
||
| #include <climits> | ||
| #include <atomic> | ||
| #include <functional> | ||
|
|
||
| #include <iostream> | ||
|
|
||
| #ifdef __linux__ | ||
|
|
||
| #include <unistd.h> | ||
| #include <linux/futex.h> | ||
| #include <sys/syscall.h> | ||
|
|
||
| #else // <- Add other operating systems here | ||
|
|
||
| // Baseline needs no new headers | ||
|
|
||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| #ifdef __linux__ | ||
|
|
||
| static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, | ||
| __cxx_contention_t __val) | ||
| { | ||
| static constexpr timespec __timeout = { 2, 0 }; | ||
| syscall(SYS_futex, __ptr, FUTEX_WAIT_PRIVATE, __val, &__timeout, 0, 0); | ||
| } | ||
|
|
||
| static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, | ||
| bool __notify_one) | ||
| { | ||
| syscall(SYS_futex, __ptr, FUTEX_WAKE_PRIVATE, __notify_one ? 1 : INT_MAX, 0, 0, 0); | ||
| } | ||
|
|
||
| #elif defined(__APPLE__) && defined(_LIBCPP_USE_ULOCK) | ||
|
|
||
| extern "C" int __ulock_wait(uint32_t operation, void *addr, uint64_t value, | ||
| uint32_t timeout); /* timeout is specified in microseconds */ | ||
| extern "C" int __ulock_wake(uint32_t operation, void *addr, uint64_t wake_value); | ||
|
|
||
| #define UL_COMPARE_AND_WAIT 1 | ||
| #define ULF_WAKE_ALL 0x00000100 | ||
|
|
||
| static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, | ||
| __cxx_contention_t __val) | ||
| { | ||
| __ulock_wait(UL_COMPARE_AND_WAIT, | ||
| const_cast<__cxx_atomic_contention_t*>(__ptr), __val, 0); | ||
| } | ||
|
|
||
| static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, | ||
| bool __notify_one) | ||
| { | ||
| __ulock_wake(UL_COMPARE_AND_WAIT | (__notify_one ? 0 : ULF_WAKE_ALL), | ||
| const_cast<__cxx_atomic_contention_t*>(__ptr), 0); | ||
| } | ||
|
|
||
| #else // <- Add other operating systems here | ||
|
|
||
| // Baseline is just a timed backoff | ||
|
|
||
| static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, | ||
| __cxx_contention_t __val) | ||
| { | ||
| __libcpp_thread_poll_with_backoff([=]() -> bool { | ||
| return !__cxx_nonatomic_compare_equal(__cxx_atomic_load(__ptr, memory_order_relaxed), __val); | ||
| }, __libcpp_timed_backoff_policy()); | ||
| } | ||
|
|
||
| static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile*, bool) { } | ||
|
|
||
| #endif // __linux__ | ||
|
|
||
| static constexpr size_t __libcpp_contention_table_size = (1 << 8); /* < there's no magic in this number */ | ||
|
|
||
| struct alignas(64) /* aim to avoid false sharing */ __libcpp_contention_table_entry | ||
| { | ||
| __cxx_atomic_contention_t __contention_state; | ||
| __cxx_atomic_contention_t __platform_state; | ||
| inline constexpr __libcpp_contention_table_entry() : | ||
| __contention_state(0), __platform_state(0) { } | ||
| }; | ||
|
|
||
| static __libcpp_contention_table_entry __libcpp_contention_table[ __libcpp_contention_table_size ]; | ||
|
|
||
| static hash<void const volatile*> __libcpp_contention_hasher; | ||
|
|
||
| static __libcpp_contention_table_entry* __libcpp_contention_state(void const volatile * p) | ||
| { | ||
| return &__libcpp_contention_table[__libcpp_contention_hasher(p) & (__libcpp_contention_table_size - 1)]; | ||
| } | ||
|
|
||
| /* Given an atomic to track contention and an atomic to actually wait on, which may be | ||
| the same atomic, we try to detect contention to avoid spuriously calling the platform. */ | ||
|
|
||
| static void __libcpp_contention_notify(__cxx_atomic_contention_t volatile* __contention_state, | ||
| __cxx_atomic_contention_t const volatile* __platform_state, | ||
| bool __notify_one) | ||
| { | ||
| if(0 != __cxx_atomic_load(__contention_state, memory_order_seq_cst)) | ||
| // We only call 'wake' if we consumed a contention bit here. | ||
| __libcpp_platform_wake_by_address(__platform_state, __notify_one); | ||
| } | ||
| static __cxx_contention_t __libcpp_contention_monitor_for_wait(__cxx_atomic_contention_t volatile* __contention_state, | ||
| __cxx_atomic_contention_t const volatile* __platform_state) | ||
| { | ||
| // We will monitor this value. | ||
| return __cxx_atomic_load(__platform_state, memory_order_acquire); | ||
| } | ||
| static void __libcpp_contention_wait(__cxx_atomic_contention_t volatile* __contention_state, | ||
| __cxx_atomic_contention_t const volatile* __platform_state, | ||
| __cxx_contention_t __old_value) | ||
| { | ||
| __cxx_atomic_fetch_add(__contention_state, __cxx_contention_t(1), memory_order_seq_cst); | ||
| // We sleep as long as the monitored value hasn't changed. | ||
| __libcpp_platform_wait_on_address(__platform_state, __old_value); | ||
| __cxx_atomic_fetch_sub(__contention_state, __cxx_contention_t(1), memory_order_release); | ||
| } | ||
|
|
||
| /* When the incoming atomic is the wrong size for the platform wait size, need to | ||
| launder the value sequence through an atomic from our table. */ | ||
|
|
||
| static void __libcpp_atomic_notify(void const volatile* __location) | ||
| { | ||
| auto const __entry = __libcpp_contention_state(__location); | ||
| // The value sequence laundering happens on the next line below. | ||
| __cxx_atomic_fetch_add(&__entry->__platform_state, __cxx_contention_t(1), memory_order_release); | ||
| __libcpp_contention_notify(&__entry->__contention_state, | ||
| &__entry->__platform_state, | ||
| false /* when laundering, we can't handle notify_one */); | ||
| } | ||
| _LIBCPP_EXPORTED_FROM_ABI | ||
| void __cxx_atomic_notify_one(void const volatile* __location) | ||
| { __libcpp_atomic_notify(__location); } | ||
| _LIBCPP_EXPORTED_FROM_ABI | ||
| void __cxx_atomic_notify_all(void const volatile* __location) | ||
| { __libcpp_atomic_notify(__location); } | ||
| _LIBCPP_EXPORTED_FROM_ABI | ||
| __cxx_contention_t __libcpp_atomic_monitor(void const volatile* __location) | ||
| { | ||
| auto const __entry = __libcpp_contention_state(__location); | ||
| return __libcpp_contention_monitor_for_wait(&__entry->__contention_state, &__entry->__platform_state); | ||
| } | ||
| _LIBCPP_EXPORTED_FROM_ABI | ||
| void __libcpp_atomic_wait(void const volatile* __location, __cxx_contention_t __old_value) | ||
| { | ||
| auto const __entry = __libcpp_contention_state(__location); | ||
| __libcpp_contention_wait(&__entry->__contention_state, &__entry->__platform_state, __old_value); | ||
| } | ||
|
|
||
| /* When the incoming atomic happens to be the platform wait size, we still need to use the | ||
| table for the contention detection, but we can use the atomic directly for the wait. */ | ||
|
|
||
| _LIBCPP_EXPORTED_FROM_ABI | ||
| void __cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile* __location) | ||
| { | ||
| __libcpp_contention_notify(&__libcpp_contention_state(__location)->__contention_state, __location, true); | ||
| } | ||
| _LIBCPP_EXPORTED_FROM_ABI | ||
| void __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile* __location) | ||
| { | ||
| __libcpp_contention_notify(&__libcpp_contention_state(__location)->__contention_state, __location, false); | ||
| } | ||
| _LIBCPP_EXPORTED_FROM_ABI | ||
| __cxx_contention_t __libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile* __location) | ||
| { | ||
| return __libcpp_contention_monitor_for_wait(&__libcpp_contention_state(__location)->__contention_state, __location); | ||
| } | ||
| _LIBCPP_EXPORTED_FROM_ABI | ||
| void __libcpp_atomic_wait(__cxx_atomic_contention_t const volatile* __location, __cxx_contention_t __old_value) | ||
| { | ||
| __libcpp_contention_wait(&__libcpp_contention_state(__location)->__contention_state, __location, __old_value); | ||
| } | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif //_LIBCPP_HAS_NO_THREADS |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| //===------------------------- barrier.cpp ---------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <__config> | ||
|
|
||
| #ifndef _LIBCPP_HAS_NO_THREADS | ||
|
|
||
| #include <barrier> | ||
| #include <thread> | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_TREE_BARRIER) && (_LIBCPP_STD_VER > 11) | ||
|
|
||
| class __barrier_algorithm_base { | ||
| public: | ||
| struct alignas(64) /* naturally-align the heap state */ __state_t | ||
| { | ||
| struct { | ||
| __atomic_base<__barrier_phase_t> __phase = ATOMIC_VAR_INIT(0); | ||
| } __tickets[64]; | ||
| }; | ||
|
|
||
| ptrdiff_t& __expected; | ||
| unique_ptr<__state_t[]> __state; | ||
|
|
||
| _LIBCPP_HIDDEN | ||
| __barrier_algorithm_base(ptrdiff_t& __expected) | ||
| : __expected(__expected), __state(new __barrier_algorithm_base::__state_t[(__expected + 1) >> 1]) | ||
| { | ||
| } | ||
| _LIBCPP_HIDDEN | ||
| bool __arrive(__barrier_phase_t __old_phase) | ||
| { | ||
| __barrier_phase_t const __half_step = __old_phase + 1, | ||
| __full_step = __old_phase + 2; | ||
| size_t __current_expected = __expected, | ||
| __current = hash<thread::id>()(this_thread::get_id()) % ((__expected + 1) >> 1); | ||
| for(int __round = 0;; ++__round) { | ||
| if(__current_expected <= 1) | ||
| return true; | ||
| size_t const __end_node = ((__current_expected + 1) >> 1), | ||
| __last_node = __end_node - 1; | ||
| for(;;++__current) { | ||
| if(__current == __end_node) | ||
| __current = 0; | ||
| __barrier_phase_t expect = __old_phase; | ||
| if(__current == __last_node && (__current_expected & 1)) | ||
| { | ||
| if(__state[__current].__tickets[__round].__phase.compare_exchange_strong(expect, __full_step, memory_order_acq_rel)) | ||
| break; // I'm 1 in 1, go to next __round | ||
| } | ||
| else if(__state[__current].__tickets[__round].__phase.compare_exchange_strong(expect, __half_step, memory_order_acq_rel)) | ||
| { | ||
| return false; // I'm 1 in 2, done with arrival | ||
| } | ||
| else if(expect == __half_step) | ||
| { | ||
| if(__state[__current].__tickets[__round].__phase.compare_exchange_strong(expect, __full_step, memory_order_acq_rel)) | ||
| break; // I'm 2 in 2, go to next __round | ||
| } | ||
| } | ||
| __current_expected = __last_node + 1; | ||
| __current >>= 1; | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| _LIBCPP_EXPORTED_FROM_ABI | ||
| __barrier_algorithm_base * __construct_barrier_algorithm_base(ptrdiff_t& __expected) | ||
| { | ||
| return new __barrier_algorithm_base(__expected); | ||
| } | ||
| _LIBCPP_EXPORTED_FROM_ABI | ||
| bool __arrive_barrier_algorithm_base(__barrier_algorithm_base* __barrier, | ||
| __barrier_phase_t __old_phase) | ||
| { | ||
| return __barrier->__arrive(__old_phase); | ||
| } | ||
| _LIBCPP_EXPORTED_FROM_ABI | ||
| void __destroy_barrier_algorithm_base(__barrier_algorithm_base* __barrier) | ||
| { | ||
| delete __barrier; | ||
| } | ||
|
|
||
| #endif //!defined(_LIBCPP_HAS_NO_TREE_BARRIER) && (_LIBCPP_STD_VER >= 11) | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif //_LIBCPP_HAS_NO_THREADS |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // XFAIL: c++98, c++03 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <atomic> | ||
|
|
||
| #include <atomic> | ||
| #include <type_traits> | ||
| #include <cassert> | ||
| #include <thread> | ||
|
|
||
| #include "test_macros.h" | ||
| #include "../atomics.types.operations.req/atomic_helpers.h" | ||
|
|
||
| template <class T> | ||
| struct TestFn { | ||
| void operator()() const { | ||
| typedef std::atomic<T> A; | ||
|
|
||
| A t; | ||
| std::atomic_init(&t, T(1)); | ||
| assert(std::atomic_load(&t) == T(1)); | ||
| std::atomic_wait(&t, T(0)); | ||
| std::thread t_([&](){ | ||
| std::atomic_store(&t, T(3)); | ||
| std::atomic_notify_one(&t); | ||
| }); | ||
| std::atomic_wait(&t, T(1)); | ||
| t_.join(); | ||
|
|
||
| volatile A vt; | ||
| std::atomic_init(&vt, T(2)); | ||
| assert(std::atomic_load(&vt) == T(2)); | ||
| std::atomic_wait(&vt, T(1)); | ||
| std::thread t2_([&](){ | ||
| std::atomic_store(&vt, T(4)); | ||
| std::atomic_notify_one(&vt); | ||
| }); | ||
| std::atomic_wait(&vt, T(2)); | ||
| t2_.join(); | ||
| } | ||
| }; | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| TestEachAtomicType<TestFn>()(); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // <atomic> | ||
|
|
||
| // Test nested types | ||
|
|
||
| // template <class T> | ||
| // class atomic | ||
| // { | ||
| // public: | ||
| // typedef T value_type; | ||
| // }; | ||
|
|
||
| #include <atomic> | ||
| #include <type_traits> | ||
|
|
||
| #include <thread> | ||
| #include <chrono> | ||
| #if TEST_STD_VER >= 20 | ||
| # include <memory> | ||
| #endif | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| template <class A> | ||
| void | ||
| test_atomic() | ||
| { | ||
| A a; | ||
| #if TEST_STD_VER >= 17 | ||
| static_assert((std::is_same<typename A::value_type, decltype(a.load())>::value), ""); | ||
| #endif | ||
| } | ||
|
|
||
| template <class T> | ||
| void | ||
| test() | ||
| { | ||
| using A = std::atomic<T>; | ||
| #if TEST_STD_VER >= 17 | ||
| static_assert((std::is_same<typename A::value_type, T>::value), ""); | ||
| #endif | ||
| test_atomic<A>(); | ||
| } | ||
|
|
||
| struct TriviallyCopyable { | ||
| int i_; | ||
| }; | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| test<bool> (); | ||
| test<char> (); | ||
| test<signed char> (); | ||
| test<unsigned char> (); | ||
| test<short> (); | ||
| test<unsigned short> (); | ||
| test<int> (); | ||
| test<unsigned int> (); | ||
| test<long> (); | ||
| test<unsigned long> (); | ||
| test<long long> (); | ||
| test<unsigned long long> (); | ||
| test<char16_t> (); | ||
| test<char32_t> (); | ||
| test<wchar_t> (); | ||
|
|
||
| test<int_least8_t> (); | ||
| test<uint_least8_t> (); | ||
| test<int_least16_t> (); | ||
| test<uint_least16_t> (); | ||
| test<int_least32_t> (); | ||
| test<uint_least32_t> (); | ||
| test<int_least64_t> (); | ||
| test<uint_least64_t> (); | ||
|
|
||
| test<int_fast8_t> (); | ||
| test<uint_fast8_t> (); | ||
| test<int_fast16_t> (); | ||
| test<uint_fast16_t> (); | ||
| test<int_fast32_t> (); | ||
| test<uint_fast32_t> (); | ||
| test<int_fast64_t> (); | ||
| test<uint_fast64_t> (); | ||
|
|
||
| test< int8_t> (); | ||
| test<uint8_t> (); | ||
| test< int16_t> (); | ||
| test<uint16_t> (); | ||
| test< int32_t> (); | ||
| test<uint32_t> (); | ||
| test< int64_t> (); | ||
| test<uint64_t> (); | ||
|
|
||
| test<intptr_t> (); | ||
| test<uintptr_t> (); | ||
| test<size_t> (); | ||
| test<ptrdiff_t> (); | ||
| test<intmax_t> (); | ||
| test<uintmax_t> (); | ||
|
|
||
| test<uintmax_t> (); | ||
| test<uintmax_t> (); | ||
|
|
||
| test<TriviallyCopyable>(); | ||
| test<std::thread::id>(); | ||
| test<std::chrono::nanoseconds>(); | ||
| test<float>(); | ||
|
|
||
| #if TEST_STD_VER >= 20 | ||
| test_atomic<std::atomic_signed_lock_free>(); | ||
| test_atomic<std::atomic_unsigned_lock_free>(); | ||
| /* | ||
| test<std::shared_ptr<int>>(); | ||
| */ | ||
| #endif | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <barrier> | ||
|
|
||
| #include <barrier> | ||
| #include <thread> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| std::barrier<> b(2); | ||
|
|
||
| auto tok = b.arrive(); | ||
| std::thread t([&](){ | ||
| (void)b.arrive(); | ||
| }); | ||
| b.wait(std::move(tok)); | ||
| t.join(); | ||
|
|
||
| auto tok2 = b.arrive(2); | ||
| b.wait(std::move(tok2)); | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <barrier> | ||
|
|
||
| #include <barrier> | ||
| #include <thread> | ||
| #include <cassert> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| std::barrier<> b(2); | ||
|
|
||
| std::thread t([&](){ | ||
| b.arrive_and_drop(); | ||
| }); | ||
|
|
||
| b.arrive_and_wait(); | ||
| b.arrive_and_wait(); | ||
| t.join(); | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <barrier> | ||
|
|
||
| #include <barrier> | ||
| #include <thread> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| std::barrier<> b(2); | ||
|
|
||
| std::thread t([&](){ | ||
| for(int i = 0; i < 10; ++i) | ||
| b.arrive_and_wait(); | ||
| }); | ||
| for(int i = 0; i < 10; ++i) | ||
| b.arrive_and_wait(); | ||
| t.join(); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <barrier> | ||
|
|
||
| #include <barrier> | ||
| #include <thread> | ||
| #include <cassert> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| int x = 0; | ||
| auto comp = [&]() { x += 1; }; | ||
| std::barrier<decltype(comp)> b(2, comp); | ||
|
|
||
| std::thread t([&](){ | ||
| for(int i = 0; i < 10; ++i) | ||
| b.arrive_and_wait(); | ||
| }); | ||
|
|
||
| for(int i = 0; i < 10; ++i) | ||
| b.arrive_and_wait(); | ||
|
|
||
| assert(x == 10); | ||
| t.join(); | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // <barrier> | ||
|
|
||
| #include <barrier> | ||
| #include <thread> | ||
| #include <cassert> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| static_assert(std::barrier<>::max() > 0, ""); | ||
| auto l = [](){}; | ||
| static_assert(std::barrier<decltype(l)>::max() > 0, ""); | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // <barrier> | ||
|
|
||
| #include <barrier> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| #ifndef _LIBCPP_VERSION | ||
| #error _LIBCPP_VERSION not defined | ||
| #endif | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <latch> | ||
|
|
||
| #include <latch> | ||
| #include <thread> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| std::latch l(2); | ||
|
|
||
| std::thread t([&](){ | ||
| l.arrive_and_wait(); | ||
| }); | ||
| l.arrive_and_wait(); | ||
| t.join(); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <latch> | ||
|
|
||
| #include <latch> | ||
| #include <thread> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| std::latch l(2); | ||
|
|
||
| l.count_down(); | ||
| std::thread t([&](){ | ||
| l.count_down(); | ||
| }); | ||
| l.wait(); | ||
| t.join(); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // <latch> | ||
|
|
||
| #include <latch> | ||
| #include <cassert> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| static_assert(std::latch::max() > 0, ""); | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <latch> | ||
|
|
||
| #include <latch> | ||
| #include <cassert> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| std::latch l(1); | ||
|
|
||
| l.count_down(); | ||
| bool const b = l.try_wait(); | ||
| assert(b); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // <latch> | ||
|
|
||
| #include <latch> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| #ifndef _LIBCPP_VERSION | ||
| #error _LIBCPP_VERSION not defined | ||
| #endif | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <semaphore> | ||
|
|
||
| #include <semaphore> | ||
| #include <thread> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| std::counting_semaphore<> s(2); | ||
|
|
||
| std::thread t([&](){ | ||
| s.acquire(); | ||
| }); | ||
| t.join(); | ||
|
|
||
| s.acquire(); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <semaphore> | ||
|
|
||
| #include <semaphore> | ||
| #include <chrono> | ||
| #include <thread> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| std::binary_semaphore s(1); | ||
|
|
||
| auto l = [&](){ | ||
| for(int i = 0; i < 1024; ++i) { | ||
| s.acquire(); | ||
| std::this_thread::sleep_for(std::chrono::microseconds(1)); | ||
| s.release(); | ||
| } | ||
| }; | ||
|
|
||
| std::thread t(l); | ||
| l(); | ||
|
|
||
| t.join(); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // <semaphore> | ||
|
|
||
| #include <semaphore> | ||
| #include <thread> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| static_assert(std::counting_semaphore<>::max() > 0, ""); | ||
| static_assert(std::counting_semaphore<1>::max() >= 1, ""); | ||
| static_assert(std::counting_semaphore<std::numeric_limits<int>::max()>::max() >= 1, ""); | ||
| static_assert(std::counting_semaphore<std::numeric_limits<unsigned>::max()>::max() >= 1, ""); | ||
| static_assert(std::counting_semaphore<std::numeric_limits<ptrdiff_t>::max()>::max() >= 1, ""); | ||
| static_assert(std::counting_semaphore<1>::max() == std::binary_semaphore::max(), ""); | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <semaphore> | ||
|
|
||
| #include <semaphore> | ||
| #include <thread> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| std::counting_semaphore<> s(0); | ||
|
|
||
| s.release(); | ||
| s.acquire(); | ||
|
|
||
| std::thread t([&](){ | ||
| s.acquire(); | ||
| }); | ||
| s.release(2); | ||
| t.join(); | ||
| s.acquire(); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <semaphore> | ||
|
|
||
| #include <semaphore> | ||
| #include <thread> | ||
| #include <chrono> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| auto const start = std::chrono::steady_clock::now(); | ||
|
|
||
| std::counting_semaphore<> s(0); | ||
|
|
||
| assert(!s.try_acquire_until(start + std::chrono::milliseconds(250))); | ||
| assert(!s.try_acquire_for(std::chrono::milliseconds(250))); | ||
|
|
||
| std::thread t([&](){ | ||
| std::this_thread::sleep_for(std::chrono::milliseconds(250)); | ||
| s.release(); | ||
| std::this_thread::sleep_for(std::chrono::milliseconds(250)); | ||
| s.release(); | ||
| }); | ||
|
|
||
| assert(s.try_acquire_until(start + std::chrono::seconds(2))); | ||
| assert(s.try_acquire_for(std::chrono::seconds(2))); | ||
| t.join(); | ||
|
|
||
| auto const end = std::chrono::steady_clock::now(); | ||
| assert(end - start < std::chrono::seconds(10)); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // This test requires the dylib support introduced in D68480 | ||
| // XFAIL: with_system_cxx_lib=macosx10.15 | ||
| // XFAIL: with_system_cxx_lib=macosx10.14 | ||
| // XFAIL: with_system_cxx_lib=macosx10.13 | ||
| // XFAIL: with_system_cxx_lib=macosx10.12 | ||
| // XFAIL: with_system_cxx_lib=macosx10.11 | ||
| // XFAIL: with_system_cxx_lib=macosx10.10 | ||
| // XFAIL: with_system_cxx_lib=macosx10.9 | ||
|
|
||
| // <semaphore> | ||
|
|
||
| #include <semaphore> | ||
| #include <thread> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| std::counting_semaphore<> s(1); | ||
|
|
||
| assert(s.try_acquire()); | ||
| s.release(); | ||
| assert(s.try_acquire()); | ||
| s.release(2); | ||
| std::thread t([&](){ | ||
| assert(s.try_acquire()); | ||
| }); | ||
| t.join(); | ||
| assert(s.try_acquire()); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // UNSUPPORTED: libcpp-has-no-threads | ||
| // UNSUPPORTED: c++98, c++03, c++11 | ||
|
|
||
| // <semaphore> | ||
|
|
||
| #include <semaphore> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| #ifndef _LIBCPP_VERSION | ||
| #error _LIBCPP_VERSION not defined | ||
| #endif | ||
|
|
||
| int main(int, char**) | ||
| { | ||
| return 0; | ||
| } |