Revert "[coroutines] Add std::experimental::task<T> type"
This revision is causing build and test failures, such as
http://lab.llvm.org:8011/builders/libcxx-libcxxabi-libunwind-armv8-linux/builds/648/steps/test.libcxx/logs/stdio,
so I'll revert it.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@357023 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 0ceee6b..9880115 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -86,7 +86,6 @@
experimental/string
experimental/string_view
experimental/system_error
- experimental/task
experimental/tuple
experimental/type_traits
experimental/unordered_map
diff --git a/include/experimental/__memory b/include/experimental/__memory
index 6da6bef..4cf8978 100644
--- a/include/experimental/__memory
+++ b/include/experimental/__memory
@@ -73,13 +73,6 @@
>
{};
-// Round __s up to next multiple of __a.
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
-size_t __aligned_allocation_size(size_t __s, size_t __a) _NOEXCEPT
-{
- return (__s + __a - 1) & ~(__a - 1);
-}
-
template <class _Tp, class _Alloc, class ..._Args>
inline _LIBCPP_INLINE_VISIBILITY
void __lfts_user_alloc_construct(
diff --git a/include/experimental/memory_resource b/include/experimental/memory_resource
index 897bd1f..f999fb9 100644
--- a/include/experimental/memory_resource
+++ b/include/experimental/memory_resource
@@ -86,6 +86,14 @@
_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR
+// Round __s up to next multiple of __a.
+inline _LIBCPP_INLINE_VISIBILITY
+size_t __aligned_allocation_size(size_t __s, size_t __a) _NOEXCEPT
+{
+ _LIBCPP_ASSERT(__s + __a > __s, "aligned allocation size overflows");
+ return (__s + __a - 1) & ~(__a - 1);
+}
+
// 8.5, memory.resource
class _LIBCPP_TYPE_VIS memory_resource
{
diff --git a/include/experimental/task b/include/experimental/task
deleted file mode 100644
index 2bdcaf2..0000000
--- a/include/experimental/task
+++ /dev/null
@@ -1,503 +0,0 @@
-// -*- C++ -*-
-//===------------------------------- task ---------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP_EXPERIMENTAL_TASK
-#define _LIBCPP_EXPERIMENTAL_TASK
-
-#include <experimental/__config>
-#include <experimental/__memory>
-#include <experimental/coroutine>
-
-#include <exception>
-#include <type_traits>
-#include <utility>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#pragma GCC system_header
-#endif
-
-#ifdef _LIBCPP_HAS_NO_COROUTINES
-#if defined(_LIBCPP_WARNING)
-_LIBCPP_WARNING("<experimental/task> cannot be used with this compiler")
-#else
-#warning <experimental/task> cannot be used with this compiler
-#endif
-#endif
-
-_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_COROUTINES
-
-////// task<T>
-
-template <typename _Tp = void>
-class task;
-
-struct __task_promise_final_awaitable {
- _LIBCPP_INLINE_VISIBILITY
- _LIBCPP_CONSTEXPR bool await_ready() const _NOEXCEPT { return false; }
-
- template <typename _TaskPromise>
- _LIBCPP_INLINE_VISIBILITY coroutine_handle<>
- await_suspend(coroutine_handle<_TaskPromise> __coro) const _NOEXCEPT {
- _LIBCPP_ASSERT(
- __coro.promise().__continuation_,
- "Coroutine completed without a valid continuation attached.");
- return __coro.promise().__continuation_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void await_resume() const _NOEXCEPT {}
-};
-
-class _LIBCPP_TYPE_VIS __task_promise_base {
- using _DeallocFunc = void(void* __ptr, size_t __size) _NOEXCEPT;
-
- template <typename _Alloc>
- static constexpr bool __allocator_needs_to_be_stored =
- !allocator_traits<_Alloc>::is_always_equal::value ||
- !is_default_constructible_v<_Alloc>;
-
- static _LIBCPP_CONSTEXPR size_t
- __get_dealloc_func_offset(size_t __frameSize) _NOEXCEPT {
- return _VSTD_LFTS::__aligned_allocation_size(__frameSize,
- alignof(_DeallocFunc*));
- }
-
- static _LIBCPP_CONSTEXPR size_t
- __get_padded_frame_size(size_t __frameSize) _NOEXCEPT {
- return __get_dealloc_func_offset(__frameSize) + sizeof(_DeallocFunc*);
- }
-
- template <typename _Alloc>
- static _LIBCPP_CONSTEXPR size_t
- __get_allocator_offset(size_t __frameSize) _NOEXCEPT {
- return _VSTD_LFTS::__aligned_allocation_size(
- __get_padded_frame_size(__frameSize), alignof(_Alloc));
- }
-
- template <typename _Alloc>
- static _LIBCPP_CONSTEXPR size_t
- __get_padded_frame_size_with_allocator(size_t __frameSize) _NOEXCEPT {
- if constexpr (__allocator_needs_to_be_stored<_Alloc>) {
- return __get_allocator_offset<_Alloc>(__frameSize) + sizeof(_Alloc);
- } else {
- return __get_padded_frame_size(__frameSize);
- }
- }
-
- _LIBCPP_INLINE_VISIBILITY
- static _DeallocFunc*& __get_dealloc_func(void* __frameStart,
- size_t __frameSize) _NOEXCEPT {
- return *reinterpret_cast<_DeallocFunc**>(
- static_cast<char*>(__frameStart) +
- __get_dealloc_func_offset(__frameSize));
- }
-
- template <typename _Alloc>
- _LIBCPP_INLINE_VISIBILITY static _Alloc&
- __get_allocator(void* __frameStart, size_t __frameSize) _NOEXCEPT {
- return *reinterpret_cast<_Alloc*>(
- static_cast<char*>(__frameStart) +
- __get_allocator_offset<_Alloc>(__frameSize));
- }
-
-public:
- __task_promise_base() _NOEXCEPT = default;
-
- // Explicitly disable special member functions.
- __task_promise_base(const __task_promise_base&) = delete;
- __task_promise_base(__task_promise_base&&) = delete;
- __task_promise_base& operator=(const __task_promise_base&) = delete;
- __task_promise_base& operator=(__task_promise_base&&) = delete;
-
- static void* operator new(size_t __size) {
- // Allocate space for an extra pointer immediately after __size that holds
- // the type-erased deallocation function.
- void* __pointer = ::operator new(__get_padded_frame_size(__size));
-
- _DeallocFunc*& __deallocFunc = __get_dealloc_func(__pointer, __size);
- __deallocFunc = [](void* __pointer, size_t __size) _NOEXCEPT {
- ::operator delete(__pointer, __get_padded_frame_size(__size));
- };
-
- return __pointer;
- }
-
- template <typename _Alloc, typename... _Args>
- static void* operator new(size_t __size, allocator_arg_t, _Alloc& __alloc,
- _Args&...) {
- using _CharAlloc =
- typename allocator_traits<_Alloc>::template rebind_alloc<char>;
-
- _CharAlloc __charAllocator{__alloc};
-
- void* __pointer = __charAllocator.allocate(
- __get_padded_frame_size_with_allocator<_CharAlloc>(__size));
-
- _DeallocFunc*& __deallocFunc = __get_dealloc_func(__pointer, __size);
- __deallocFunc = [](void* __pointer, size_t __size) _NOEXCEPT {
- // Allocators are required to not throw from their move constructors
- // however they aren't required to be declared noexcept so we can't
- // actually check this with a static_assert.
- //
- // static_assert(is_nothrow_move_constructible<_Alloc>::value,
- // "task<T> coroutine custom allocator requires a noexcept "
- // "move constructor");
-
- size_t __paddedSize =
- __get_padded_frame_size_with_allocator<_CharAlloc>(__size);
-
- if constexpr (__allocator_needs_to_be_stored<_CharAlloc>) {
- _CharAlloc& __allocatorInFrame =
- __get_allocator<_CharAlloc>(__pointer, __size);
- _CharAlloc __allocatorOnStack = _VSTD::move(__allocatorInFrame);
- __allocatorInFrame.~_CharAlloc();
- // Allocator requirements state that deallocate() must not throw.
- // See [allocator.requirements] from C++ standard.
- // We are relying on that here.
- __allocatorOnStack.deallocate(static_cast<char*>(__pointer),
- __paddedSize);
- } else {
- _CharAlloc __alloc;
- __alloc.deallocate(static_cast<char*>(__pointer), __paddedSize);
- }
- };
-
- // Copy the allocator into the heap frame (if required)
- if constexpr (__allocator_needs_to_be_stored<_CharAlloc>) {
- // task<T> coroutine custom allocation requires the copy constructor to
- // not throw but we can't rely on it being declared noexcept.
- // If it did throw we'd leak the allocation here.
- ::new (static_cast<void*>(
- _VSTD::addressof(__get_allocator<_CharAlloc>(__pointer, __size))))
- _CharAlloc(_VSTD::move(__charAllocator));
- }
-
- return __pointer;
- }
-
- template <typename _This, typename _Alloc, typename... _Args>
- static void* operator new(size_t __size, _This&, allocator_arg_t __allocArg, _Alloc& __alloc,
- _Args&...) {
- return __task_promise_base::operator new(__size, __allocArg, __alloc);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- static void operator delete(void* __pointer, size_t __size)_NOEXCEPT {
- __get_dealloc_func(__pointer, __size)(__pointer, __size);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- suspend_always initial_suspend() const _NOEXCEPT { return {}; }
-
- _LIBCPP_INLINE_VISIBILITY
- __task_promise_final_awaitable final_suspend() _NOEXCEPT { return {}; }
-
- _LIBCPP_INLINE_VISIBILITY
- void __set_continuation(coroutine_handle<> __continuation) {
- _LIBCPP_ASSERT(!__continuation_, "task already has a continuation");
- __continuation_ = __continuation;
- }
-
-private:
- friend struct __task_promise_final_awaitable;
-
- coroutine_handle<> __continuation_;
-};
-
-template <typename _Tp>
-class _LIBCPP_TEMPLATE_VIS __task_promise final : public __task_promise_base {
- using _Handle = coroutine_handle<__task_promise>;
-
-public:
- __task_promise() _NOEXCEPT : __state_(_State::__no_value) {}
-
- ~__task_promise() {
- switch (__state_) {
- case _State::__value:
- __value_.~_Tp();
- break;
-#ifndef _LIBCPP_NO_EXCEPTIONS
- case _State::__exception:
- __exception_.~exception_ptr();
- break;
-#endif
- case _State::__no_value:
- break;
- };
- }
-
- _LIBCPP_INLINE_VISIBILITY
- task<_Tp> get_return_object() _NOEXCEPT;
-
- void unhandled_exception() _NOEXCEPT {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- ::new (static_cast<void*>(&__exception_))
- exception_ptr(current_exception());
- __state_ = _State::__exception;
-#else
- _LIBCPP_ASSERT(
- false, "task<T> coroutine unexpectedly called unhandled_exception()");
-#endif
- }
-
- // Only enable return_value() overload if _Tp is implicitly constructible from
- // _Value
- template <typename _Value,
- enable_if_t<is_convertible<_Value, _Tp>::value, int> = 0>
- void return_value(_Value&& __value)
- _NOEXCEPT_((is_nothrow_constructible_v<_Tp, _Value>)) {
- __construct_value(static_cast<_Value&&>(__value));
- }
-
- template <typename _Value>
- auto return_value(std::initializer_list<_Value> __initializer) _NOEXCEPT_(
- (is_nothrow_constructible_v<_Tp, std::initializer_list<_Value>>))
- -> std::enable_if_t<
- std::is_constructible_v<_Tp, std::initializer_list<_Value>>> {
- __construct_value(_VSTD::move(__initializer));
- }
-
- auto return_value(_Tp&& __value)
- _NOEXCEPT_((is_nothrow_move_constructible_v<_Tp>))
- -> std::enable_if_t<std::is_move_constructible_v<_Tp>> {
- __construct_value(static_cast<_Tp&&>(__value));
- }
-
- _Tp& __lvalue_result() {
- __throw_if_exception();
- return __value_;
- }
-
- _Tp __rvalue_result() {
- __throw_if_exception();
- return static_cast<_Tp&&>(__value_);
- }
-
-private:
- template <typename... _Args>
- void __construct_value(_Args&&... __args) {
- ::new (static_cast<void*>(_VSTD::addressof(__value_)))
- _Tp(static_cast<_Args&&>(__args)...);
-
- // Only set __state_ after successfully constructing the value.
- // If constructor throws then state will be updated by
- // unhandled_exception().
- __state_ = _State::__value;
- }
-
- void __throw_if_exception() {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- if (__state_ == _State::__exception) {
- rethrow_exception(__exception_);
- }
-#endif
- }
-
- enum class _State { __no_value, __value, __exception };
-
- _State __state_ = _State::__no_value;
- union {
- char __empty_;
- _Tp __value_;
- exception_ptr __exception_;
- };
-};
-
-template <typename _Tp>
-class __task_promise<_Tp&> final : public __task_promise_base {
- using _Ptr = _Tp*;
- using _Handle = coroutine_handle<__task_promise>;
-
-public:
- __task_promise() _NOEXCEPT = default;
-
- ~__task_promise() {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- if (__has_exception_) {
- __exception_.~exception_ptr();
- }
-#endif
- }
-
- _LIBCPP_INLINE_VISIBILITY
- task<_Tp&> get_return_object() _NOEXCEPT;
-
- void unhandled_exception() _NOEXCEPT {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- ::new (static_cast<void*>(&__exception_))
- exception_ptr(current_exception());
- __has_exception_ = true;
-#else
- _LIBCPP_ASSERT(
- false, "task<T> coroutine unexpectedly called unhandled_exception()");
-#endif
- }
-
- void return_value(_Tp& __value) _NOEXCEPT {
- ::new (static_cast<void*>(&__pointer_)) _Ptr(_VSTD::addressof(__value));
- }
-
- _Tp& __lvalue_result() {
- __throw_if_exception();
- return *__pointer_;
- }
-
- _Tp& __rvalue_result() { return __lvalue_result(); }
-
-private:
- void __throw_if_exception() {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- if (__has_exception_) {
- rethrow_exception(__exception_);
- }
-#endif
- }
-
- union {
- char __empty_;
- _Ptr __pointer_;
- exception_ptr __exception_;
- };
- bool __has_exception_ = false;
-};
-
-template <>
-class __task_promise<void> final : public __task_promise_base {
- using _Handle = coroutine_handle<__task_promise>;
-
-public:
- task<void> get_return_object() _NOEXCEPT;
-
- void return_void() _NOEXCEPT {}
-
- void unhandled_exception() _NOEXCEPT {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- __exception_ = current_exception();
-#endif
- }
-
- void __lvalue_result() { __throw_if_exception(); }
-
- void __rvalue_result() { __throw_if_exception(); }
-
-private:
- void __throw_if_exception() {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- if (__exception_) {
- rethrow_exception(__exception_);
- }
-#endif
- }
-
- exception_ptr __exception_;
-};
-
-template <typename _Tp>
-class _LIBCPP_TEMPLATE_VIS _LIBCPP_NODISCARD_AFTER_CXX17 task {
-public:
- using promise_type = __task_promise<_Tp>;
-
-private:
- using _Handle = coroutine_handle<__task_promise<_Tp>>;
-
- class _AwaiterBase {
- public:
- _AwaiterBase(_Handle __coro) _NOEXCEPT : __coro_(__coro) {}
-
- _LIBCPP_INLINE_VISIBILITY
- bool await_ready() const { return __coro_.done(); }
-
- _LIBCPP_INLINE_VISIBILITY
- _Handle await_suspend(coroutine_handle<> __continuation) const {
- __coro_.promise().__set_continuation(__continuation);
- return __coro_;
- }
-
- protected:
- _Handle __coro_;
- };
-
-public:
- _LIBCPP_INLINE_VISIBILITY
- task(task&& __other) _NOEXCEPT
- : __coro_(_VSTD::exchange(__other.__coro_, {})) {}
-
- task(const task&) = delete;
- task& operator=(const task&) = delete;
-
- _LIBCPP_INLINE_VISIBILITY
- ~task() {
- if (__coro_)
- __coro_.destroy();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void swap(task& __other) _NOEXCEPT { _VSTD::swap(__coro_, __other.__coro_); }
-
- _LIBCPP_INLINE_VISIBILITY
- auto operator co_await() & {
- class _Awaiter : public _AwaiterBase {
- public:
- using _AwaiterBase::_AwaiterBase;
-
- _LIBCPP_INLINE_VISIBILITY
- decltype(auto) await_resume() {
- return this->__coro_.promise().__lvalue_result();
- }
- };
-
- _LIBCPP_ASSERT(__coro_,
- "Undefined behaviour to co_await an invalid task<T>");
- return _Awaiter{__coro_};
- }
-
- _LIBCPP_INLINE_VISIBILITY
- auto operator co_await() && {
- class _Awaiter : public _AwaiterBase {
- public:
- using _AwaiterBase::_AwaiterBase;
-
- _LIBCPP_INLINE_VISIBILITY
- decltype(auto) await_resume() {
- return this->__coro_.promise().__rvalue_result();
- }
- };
-
- _LIBCPP_ASSERT(__coro_,
- "Undefined behaviour to co_await an invalid task<T>");
- return _Awaiter{__coro_};
- }
-
-private:
- friend class __task_promise<_Tp>;
-
- _LIBCPP_INLINE_VISIBILITY
- task(_Handle __coro) _NOEXCEPT : __coro_(__coro) {}
-
- _Handle __coro_;
-};
-
-template <typename _Tp>
-task<_Tp> __task_promise<_Tp>::get_return_object() _NOEXCEPT {
- return task<_Tp>{_Handle::from_promise(*this)};
-}
-
-template <typename _Tp>
-task<_Tp&> __task_promise<_Tp&>::get_return_object() _NOEXCEPT {
- return task<_Tp&>{_Handle::from_promise(*this)};
-}
-
-task<void> __task_promise<void>::get_return_object() _NOEXCEPT {
- return task<void>{_Handle::from_promise(*this)};
-}
-
-_LIBCPP_END_NAMESPACE_EXPERIMENTAL_COROUTINES
-
-#endif
diff --git a/include/module.modulemap b/include/module.modulemap
index 9601527..bbfe90e 100644
--- a/include/module.modulemap
+++ b/include/module.modulemap
@@ -579,10 +579,6 @@
header "experimental/string"
export *
}
- module task {
- header "experimental/task"
- export *
- }
module type_traits {
header "experimental/type_traits"
export *
diff --git a/test/std/experimental/task/awaitable_traits.hpp b/test/std/experimental/task/awaitable_traits.hpp
deleted file mode 100644
index 3d4ba16..0000000
--- a/test/std/experimental/task/awaitable_traits.hpp
+++ /dev/null
@@ -1,117 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP_TEST_EXPERIMENTAL_TASK_AWAITABLE_TRAITS
-#define _LIBCPP_TEST_EXPERIMENTAL_TASK_AWAITABLE_TRAITS
-
-#include <type_traits>
-#include <experimental/coroutine>
-
-_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_COROUTINES
-
-template<typename _Tp>
-struct __is_coroutine_handle : std::false_type {};
-
-template<typename _Tp>
-struct __is_coroutine_handle<std::experimental::coroutine_handle<_Tp>> :
- std::true_type
-{};
-
-template<typename _Tp>
-struct __is_valid_await_suspend_result :
- std::disjunction<
- std::is_void<_Tp>,
- std::is_same<_Tp, bool>,
- __is_coroutine_handle<_Tp>>
-{};
-
-template<typename _Tp, typename = void>
-struct is_awaiter : std::false_type {};
-
-template<typename _Tp>
-struct is_awaiter<_Tp, std::void_t<
- decltype(std::declval<_Tp&>().await_ready()),
- decltype(std::declval<_Tp&>().await_resume()),
- decltype(std::declval<_Tp&>().await_suspend(
- std::declval<std::experimental::coroutine_handle<void>>()))>> :
- std::conjunction<
- std::is_same<decltype(std::declval<_Tp&>().await_ready()), bool>,
- __is_valid_await_suspend_result<decltype(
- std::declval<_Tp&>().await_suspend(
- std::declval<std::experimental::coroutine_handle<void>>()))>>
-{};
-
-template<typename _Tp>
-constexpr bool is_awaiter_v = is_awaiter<_Tp>::value;
-
-template<typename _Tp, typename = void>
-struct __has_member_operator_co_await : std::false_type {};
-
-template<typename _Tp>
-struct __has_member_operator_co_await<_Tp, std::void_t<decltype(std::declval<_Tp>().operator co_await())>>
-: is_awaiter<decltype(std::declval<_Tp>().operator co_await())>
-{};
-
-template<typename _Tp, typename = void>
-struct __has_non_member_operator_co_await : std::false_type {};
-
-template<typename _Tp>
-struct __has_non_member_operator_co_await<_Tp, std::void_t<decltype(operator co_await(std::declval<_Tp>()))>>
-: is_awaiter<decltype(operator co_await(std::declval<_Tp>()))>
-{};
-
-template<typename _Tp>
-struct is_awaitable : std::disjunction<
- is_awaiter<_Tp>,
- __has_member_operator_co_await<_Tp>,
- __has_non_member_operator_co_await<_Tp>>
-{};
-
-template<typename _Tp>
-constexpr bool is_awaitable_v = is_awaitable<_Tp>::value;
-
-template<
- typename _Tp,
- std::enable_if_t<is_awaitable_v<_Tp>, int> = 0>
-decltype(auto) get_awaiter(_Tp&& __awaitable)
-{
- if constexpr (__has_member_operator_co_await<_Tp>::value)
- {
- return static_cast<_Tp&&>(__awaitable).operator co_await();
- }
- else if constexpr (__has_non_member_operator_co_await<_Tp>::value)
- {
- return operator co_await(static_cast<_Tp&&>(__awaitable));
- }
- else
- {
- return static_cast<_Tp&&>(__awaitable);
- }
-}
-
-template<typename _Tp, typename = void>
-struct await_result
-{};
-
-template<typename _Tp>
-struct await_result<_Tp, std::enable_if_t<is_awaitable_v<_Tp>>>
-{
-private:
- using __awaiter = decltype(get_awaiter(std::declval<_Tp>()));
-public:
- using type = decltype(std::declval<__awaiter&>().await_resume());
-};
-
-template<typename _Tp>
-using await_result_t = typename await_result<_Tp>::type;
-
-_LIBCPP_END_NAMESPACE_EXPERIMENTAL_COROUTINES
-
-#endif
diff --git a/test/std/experimental/task/counted.hpp b/test/std/experimental/task/counted.hpp
deleted file mode 100644
index 50658d2..0000000
--- a/test/std/experimental/task/counted.hpp
+++ /dev/null
@@ -1,96 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP_TEST_EXPERIMENTAL_TASK_COUNTED
-#define _LIBCPP_TEST_EXPERIMENTAL_TASK_COUNTED
-
-class counted
-{
-public:
-
- counted() : id_(nextId_++)
- {
- ++defaultConstructedCount_;
- }
-
- counted(const counted& other) : id_(other.id_)
- {
- ++copyConstructedCount_;
- }
-
- counted(counted&& other) : id_(std::exchange(other.id_, 0))
- {
- ++moveConstructedCount_;
- }
-
- ~counted()
- {
- ++destructedCount_;
- }
-
- static void reset()
- {
- nextId_ = 1;
- defaultConstructedCount_ = 0;
- copyConstructedCount_ = 0;
- moveConstructedCount_ = 0;
- destructedCount_ = 0;
- }
-
- static std::size_t active_instance_count()
- {
- return
- defaultConstructedCount_ +
- copyConstructedCount_ +
- moveConstructedCount_ -
- destructedCount_;
- }
-
- static std::size_t copy_constructor_count()
- {
- return copyConstructedCount_;
- }
-
- static std::size_t move_constructor_count()
- {
- return moveConstructedCount_;
- }
-
- static std::size_t default_constructor_count()
- {
- return defaultConstructedCount_;
- }
-
- static std::size_t destructor_count()
- {
- return destructedCount_;
- }
-
- std::size_t id() const { return id_; }
-
-private:
- std::size_t id_;
-
- static std::size_t nextId_;
- static std::size_t defaultConstructedCount_;
- static std::size_t copyConstructedCount_;
- static std::size_t moveConstructedCount_;
- static std::size_t destructedCount_;
-
-};
-
-#define DEFINE_COUNTED_VARIABLES() \
- std::size_t counted::nextId_; \
- std::size_t counted::defaultConstructedCount_; \
- std::size_t counted::copyConstructedCount_; \
- std::size_t counted::moveConstructedCount_; \
- std::size_t counted::destructedCount_
-
-#endif
diff --git a/test/std/experimental/task/lit.local.cfg b/test/std/experimental/task/lit.local.cfg
deleted file mode 100644
index a0b3de8..0000000
--- a/test/std/experimental/task/lit.local.cfg
+++ /dev/null
@@ -1,9 +0,0 @@
-# If the compiler doesn't support coroutines mark all of the tests under
-# this directory as unsupported. Otherwise add the required `-fcoroutines-ts`
-# flag.
-if 'fcoroutines-ts' not in config.available_features:
- config.unsupported = True
-else:
- import copy
- config.test_format.cxx = copy.deepcopy(config.test_format.cxx)
- config.test_format.cxx.compile_flags += ['-fcoroutines-ts']
diff --git a/test/std/experimental/task/manual_reset_event.hpp b/test/std/experimental/task/manual_reset_event.hpp
deleted file mode 100644
index cfd5322..0000000
--- a/test/std/experimental/task/manual_reset_event.hpp
+++ /dev/null
@@ -1,127 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP_TEST_EXPERIMENTAL_TASK_MANUAL_RESET_EVENT
-#define _LIBCPP_TEST_EXPERIMENTAL_TASK_MANUAL_RESET_EVENT
-
-#include <experimental/coroutine>
-#include <atomic>
-
-// manual_reset_event is a coroutine synchronisation tool that allows one
-// coroutine to await the event object and if the event was not crrently
-// in the 'set' state then will suspend the awaiting coroutine until some
-// thread calls .set() on the event.
-class manual_reset_event
-{
- friend class _Awaiter;
-
- class _Awaiter
- {
- public:
-
- _Awaiter(const manual_reset_event* __event) noexcept
- : __event_(__event)
- {}
-
- bool await_ready() const noexcept
- {
- return __event_->is_set();
- }
-
- bool await_suspend(std::experimental::coroutine_handle<> __coro) noexcept
- {
- _LIBCPP_ASSERT(
- __event_->__state_.load(std::memory_order_relaxed) !=
- __State::__not_set_waiting_coroutine,
- "This manual_reset_event already has another coroutine awaiting it. "
- "Only one awaiting coroutine is supported."
- );
-
- __event_->__awaitingCoroutine_ = __coro;
-
- // If the compare-exchange fails then this means that the event was
- // already 'set' and so we should not suspend - this code path requires
- // 'acquire' semantics so we have visibility of writes prior to the
- // .set() operation that transitioned the event to the 'set' state.
- // If the compare-exchange succeeds then this needs 'release' semantics
- // so that a subsequent call to .set() has visibility of our writes
- // to the coroutine frame and to __event_->__awaitingCoroutine_ after
- // reading our write to __event_->__state_.
- _State oldState = _State::__not_set;
- return __event_->__state_.compare_exchange_strong(
- oldState,
- _State::__not_set_waiting_coroutine,
- std::memory_order_release,
- std::memory_order_acquire);
- }
-
- void await_resume() const noexcept {}
-
- private:
- const manual_reset_event* __event_;
- };
-
-public:
-
- manual_reset_event(bool __initiallySet = false) noexcept
- : __state_(__initiallySet ? _State::__set : _State::__not_set)
- {}
-
- bool is_set() const noexcept
- {
- return __state_.load(std::memory_order_acquire) == _State::__set;
- }
-
- void set() noexcept
- {
- // Needs to be 'acquire' in case the old value was a waiting coroutine
- // so that we have visibility of the writes to the coroutine frame in
- // the current thrad before we resume it.
- // Also needs to be 'release' in case the old value was 'not-set' so that
- // another thread that subsequently awaits the
- _State oldState = __state_.exchange(_State::__set, std::memory_order_acq_rel);
- if (oldState == _State::__not_set_waiting_coroutine)
- {
- _VSTD::exchange(__awaitingCoroutine_, {}).resume();
- }
- }
-
- void reset() noexcept
- {
- _LIBCPP_ASSERT(
- __state_.load(std::memory_order_relaxed) != _State::__not_set_waiting_coroutine,
- "Illegal to call reset() if a coroutine is currently awaiting the event.");
-
- // Note, we use 'relaxed' memory order here since it considered a
- // data-race to call reset() concurrently either with operator co_await()
- // or with set().
- __state_.store(_State::__not_set, std::memory_order_relaxed);
- }
-
- auto operator co_await() const noexcept
- {
- return _Awaiter{ this };
- }
-
-private:
-
- enum class _State {
- __not_set,
- __not_set_waiting_coroutine,
- __set
- };
-
- // TODO: Can we combine these two members into a single std::atomic<void*>?
- mutable std::atomic<_State> __state_;
- mutable std::experimental::coroutine_handle<> __awaitingCoroutine_;
-
-};
-
-#endif
diff --git a/test/std/experimental/task/sync_wait.hpp b/test/std/experimental/task/sync_wait.hpp
deleted file mode 100644
index 42c629e..0000000
--- a/test/std/experimental/task/sync_wait.hpp
+++ /dev/null
@@ -1,284 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP_TEST_EXPERIMENTAL_TASK_SYNC_WAIT
-#define _LIBCPP_TEST_EXPERIMENTAL_TASK_SYNC_WAIT
-
-#include <experimental/__config>
-#include <experimental/coroutine>
-#include <type_traits>
-#include <mutex>
-#include <condition_variable>
-
-#include "awaitable_traits.hpp"
-
-_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_COROUTINES
-
-// Thread-synchronisation helper that allows one thread to block in a call
-// to .wait() until another thread signals the thread by calling .set().
-class __oneshot_event
-{
-public:
- __oneshot_event() : __isSet_(false) {}
-
- void set() noexcept
- {
- unique_lock<mutex> __lock{ __mutex_ };
- __isSet_ = true;
- __cv_.notify_all();
- }
-
- void wait() noexcept
- {
- unique_lock<mutex> __lock{ __mutex_ };
- __cv_.wait(__lock, [this] { return __isSet_; });
- }
-
-private:
- mutex __mutex_;
- condition_variable __cv_;
- bool __isSet_;
-};
-
-template<typename _Derived>
-class __sync_wait_promise_base
-{
-public:
-
- using __handle_t = coroutine_handle<_Derived>;
-
-private:
-
- struct _FinalAwaiter
- {
- bool await_ready() noexcept { return false; }
- void await_suspend(__handle_t __coro) noexcept
- {
- __sync_wait_promise_base& __promise = __coro.promise();
- __promise.__event_.set();
- }
- void await_resume() noexcept {}
- };
-
- friend struct _FinalAwaiter;
-
-public:
-
- __handle_t get_return_object() { return __handle(); }
- suspend_always initial_suspend() { return {}; }
- _FinalAwaiter final_suspend() { return {}; }
-
-private:
-
- __handle_t __handle() noexcept
- {
- return __handle_t::from_promise(static_cast<_Derived&>(*this));
- }
-
-protected:
-
- // Start the coroutine and then block waiting for it to finish.
- void run() noexcept
- {
- __handle().resume();
- __event_.wait();
- }
-
-private:
-
- __oneshot_event __event_;
-
-};
-
-template<typename _Tp>
-class __sync_wait_promise final
- : public __sync_wait_promise_base<__sync_wait_promise<_Tp>>
-{
-public:
-
- __sync_wait_promise() : __state_(_State::__empty) {}
-
- ~__sync_wait_promise()
- {
- switch (__state_)
- {
- case _State::__empty:
- case _State::__value:
- break;
-#ifndef _LIBCPP_NO_EXCEPTIONS
- case _State::__exception:
- __exception_.~exception_ptr();
- break;
-#endif
- }
- }
-
- void return_void() noexcept
- {
- // Should be unreachable since coroutine should always
- // suspend at `co_yield` point where it will be destroyed
- // or will fail with an exception and bypass return_void()
- // and call unhandled_exception() instead.
- std::abort();
- }
-
- void unhandled_exception() noexcept
- {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- ::new (static_cast<void*>(&__exception_)) exception_ptr(
- std::current_exception());
- __state_ = _State::__exception;
-#else
- _VSTD::abort();
-#endif
- }
-
- auto yield_value(_Tp&& __value) noexcept
- {
- __valuePtr_ = std::addressof(__value);
- __state_ = _State::__value;
- return this->final_suspend();
- }
-
- _Tp&& get()
- {
- this->run();
-
-#ifndef _LIBCPP_NO_EXCEPTIONS
- if (__state_ == _State::__exception)
- {
- std::rethrow_exception(_VSTD::move(__exception_));
- }
-#endif
-
- return static_cast<_Tp&&>(*__valuePtr_);
- }
-
-private:
-
- enum class _State {
- __empty,
- __value,
- __exception
- };
-
- _State __state_;
- union {
- std::add_pointer_t<_Tp> __valuePtr_;
- std::exception_ptr __exception_;
- };
-
-};
-
-template<>
-struct __sync_wait_promise<void> final
- : public __sync_wait_promise_base<__sync_wait_promise<void>>
-{
-public:
-
- void unhandled_exception() noexcept
- {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- __exception_ = std::current_exception();
-#endif
- }
-
- void return_void() noexcept {}
-
- void get()
- {
- this->run();
-
-#ifndef _LIBCPP_NO_EXCEPTIONS
- if (__exception_)
- {
- std::rethrow_exception(_VSTD::move(__exception_));
- }
-#endif
- }
-
-private:
-
- std::exception_ptr __exception_;
-
-};
-
-template<typename _Tp>
-class __sync_wait_task final
-{
-public:
- using promise_type = __sync_wait_promise<_Tp>;
-
-private:
- using __handle_t = typename promise_type::__handle_t;
-
-public:
-
- __sync_wait_task(__handle_t __coro) noexcept : __coro_(__coro) {}
-
- ~__sync_wait_task()
- {
- _LIBCPP_ASSERT(__coro_, "Should always have a valid coroutine handle");
- __coro_.destroy();
- }
-
- decltype(auto) get()
- {
- return __coro_.promise().get();
- }
-private:
- __handle_t __coro_;
-};
-
-template<typename _Tp>
-struct __remove_rvalue_reference
-{
- using type = _Tp;
-};
-
-template<typename _Tp>
-struct __remove_rvalue_reference<_Tp&&>
-{
- using type = _Tp;
-};
-
-template<typename _Tp>
-using __remove_rvalue_reference_t =
- typename __remove_rvalue_reference<_Tp>::type;
-
-template<
- typename _Awaitable,
- typename _AwaitResult = await_result_t<_Awaitable>,
- std::enable_if_t<std::is_void_v<_AwaitResult>, int> = 0>
-__sync_wait_task<_AwaitResult> __make_sync_wait_task(_Awaitable&& __awaitable)
-{
- co_await static_cast<_Awaitable&&>(__awaitable);
-}
-
-template<
- typename _Awaitable,
- typename _AwaitResult = await_result_t<_Awaitable>,
- std::enable_if_t<!std::is_void_v<_AwaitResult>, int> = 0>
-__sync_wait_task<_AwaitResult> __make_sync_wait_task(_Awaitable&& __awaitable)
-{
- co_yield co_await static_cast<_Awaitable&&>(__awaitable);
-}
-
-template<typename _Awaitable>
-auto sync_wait(_Awaitable&& __awaitable)
- -> __remove_rvalue_reference_t<await_result_t<_Awaitable>>
-{
- return _VSTD_CORO::__make_sync_wait_task(
- static_cast<_Awaitable&&>(__awaitable)).get();
-}
-
-_LIBCPP_END_NAMESPACE_EXPERIMENTAL_COROUTINES
-
-#endif
diff --git a/test/std/experimental/task/task.basic/task_custom_allocator.pass.cpp b/test/std/experimental/task/task.basic/task_custom_allocator.pass.cpp
deleted file mode 100644
index bc7e598..0000000
--- a/test/std/experimental/task/task.basic/task_custom_allocator.pass.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03, c++11, c++14
-
-#include <experimental/task>
-#include <cstdlib>
-#include <cassert>
-#include <vector>
-#include <memory>
-#include <experimental/memory_resource>
-
-#include "../sync_wait.hpp"
-
-namespace coro = std::experimental::coroutines_v1;
-
-namespace
-{
- static size_t allocator_instance_count = 0;
-
- // A custom allocator that tracks the number of allocator instances that
- // have been constructed/destructed as well as the number of bytes that
- // have been allocated/deallocated using the allocator.
- template<typename T>
- class my_allocator {
- public:
- using value_type = T;
- using size_type = std::size_t;
- using difference_type = std::ptrdiff_t;
- using is_always_equal = std::false_type;
-
- explicit my_allocator(
- std::shared_ptr<size_type> totalAllocated) noexcept
- : totalAllocated_(std::move(totalAllocated))
- {
- ++allocator_instance_count;
- assert(totalAllocated_);
- }
-
- my_allocator(const my_allocator& other)
- : totalAllocated_(other.totalAllocated_)
- {
- ++allocator_instance_count;
- }
-
- my_allocator(my_allocator&& other)
- : totalAllocated_(std::move(other.totalAllocated_))
- {
- ++allocator_instance_count;
- }
-
- template<typename U>
- my_allocator(const my_allocator<U>& other)
- : totalAllocated_(other.totalAllocated_)
- {
- ++allocator_instance_count;
- }
-
- template<typename U>
- my_allocator(my_allocator<U>&& other)
- : totalAllocated_(std::move(other.totalAllocated_))
- {
- ++allocator_instance_count;
- }
-
- ~my_allocator()
- {
- --allocator_instance_count;
- }
-
- char* allocate(size_t n) {
- const auto byteCount = n * sizeof(T);
- void* p = std::malloc(byteCount);
- if (!p) {
- throw std::bad_alloc{};
- }
- *totalAllocated_ += byteCount;
- return static_cast<char*>(p);
- }
-
- void deallocate(char* p, size_t n) {
- const auto byteCount = n * sizeof(T);
- *totalAllocated_ -= byteCount;
- std::free(p);
- }
- private:
- template<typename U>
- friend class my_allocator;
-
- std::shared_ptr<size_type> totalAllocated_;
- };
-}
-
-template<typename Allocator>
-coro::task<void> f(std::allocator_arg_t, [[maybe_unused]] Allocator alloc)
-{
- co_return;
-}
-
-void test_custom_allocator_is_destructed()
-{
- auto totalAllocated = std::make_shared<size_t>(0);
-
- assert(allocator_instance_count == 0);
-
- {
- std::vector<coro::task<>> tasks;
- tasks.push_back(
- f(std::allocator_arg, my_allocator<char>{ totalAllocated }));
- tasks.push_back(
- f(std::allocator_arg, my_allocator<char>{ totalAllocated }));
-
- assert(allocator_instance_count == 4);
- assert(*totalAllocated > 0);
- }
-
- assert(allocator_instance_count == 0);
- assert(*totalAllocated == 0);
-}
-
-void test_custom_allocator_type_rebinding()
-{
- auto totalAllocated = std::make_shared<size_t>(0);
- {
- std::vector<coro::task<>> tasks;
- tasks.emplace_back(
- f(std::allocator_arg, my_allocator<int>{ totalAllocated }));
- coro::sync_wait(tasks[0]);
- }
- assert(*totalAllocated == 0);
- assert(allocator_instance_count == 0);
-}
-
-void test_mixed_custom_allocator_type_erasure()
-{
- assert(allocator_instance_count == 0);
-
- // Show that different allocators can be used within a vector of tasks
- // of the same type. ie. that the allocator is type-erased inside the
- // coroutine.
- std::vector<coro::task<>> tasks;
- tasks.push_back(f(
- std::allocator_arg, std::allocator<char>{}));
- tasks.push_back(f(
- std::allocator_arg,
- std::experimental::pmr::polymorphic_allocator<char>{
- std::experimental::pmr::new_delete_resource() }));
- tasks.push_back(f(
- std::allocator_arg,
- my_allocator<char>{ std::make_shared<size_t>(0) }));
-
- assert(allocator_instance_count > 0);
-
- for (auto& t : tasks)
- {
- coro::sync_wait(t);
- }
-
- tasks.clear();
-
- assert(allocator_instance_count == 0);
-}
-
-template<typename Allocator>
-coro::task<int> add_async(std::allocator_arg_t, [[maybe_unused]] Allocator alloc, int a, int b)
-{
- co_return a + b;
-}
-
-void test_task_custom_allocator_with_extra_args()
-{
- std::vector<coro::task<int>> tasks;
-
- for (int i = 0; i < 5; ++i) {
- tasks.push_back(add_async(
- std::allocator_arg,
- std::allocator<char>{},
- i, 2 * i));
- }
-
- for (int i = 0; i < 5; ++i)
- {
- assert(sync_wait(std::move(tasks[i])) == 3 * i);
- }
-}
-
-struct some_type {
- template<typename Allocator>
- coro::task<int> get_async(std::allocator_arg_t, [[maybe_unused]] Allocator alloc) {
- co_return 42;
- }
-
- template<typename Allocator>
- coro::task<int> add_async(std::allocator_arg_t, [[maybe_unused]] Allocator alloc, int a, int b) {
- co_return a + b;
- }
-};
-
-void test_task_custom_allocator_on_member_function()
-{
- assert(allocator_instance_count == 0);
-
- auto totalAllocated = std::make_shared<size_t>(0);
- some_type obj;
- assert(sync_wait(obj.get_async(std::allocator_arg, std::allocator<char>{})) == 42);
- assert(sync_wait(obj.get_async(std::allocator_arg, my_allocator<char>{totalAllocated})) == 42);
- assert(sync_wait(obj.add_async(std::allocator_arg, std::allocator<char>{}, 2, 3)) == 5);
- assert(sync_wait(obj.add_async(std::allocator_arg, my_allocator<char>{totalAllocated}, 2, 3)) == 5);
-
- assert(allocator_instance_count == 0);
- assert(*totalAllocated == 0);
-}
-
-int main()
-{
- test_custom_allocator_is_destructed();
- test_custom_allocator_type_rebinding();
- test_mixed_custom_allocator_type_erasure();
- test_task_custom_allocator_with_extra_args();
- test_task_custom_allocator_on_member_function();
-
- return 0;
-}
diff --git a/test/std/experimental/task/task.basic/task_of_value.pass.cpp b/test/std/experimental/task/task.basic/task_of_value.pass.cpp
deleted file mode 100644
index 0d5a8c9..0000000
--- a/test/std/experimental/task/task.basic/task_of_value.pass.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03, c++11, c++14
-
-#include <experimental/task>
-#include <string>
-#include <vector>
-#include <memory>
-#include "../sync_wait.hpp"
-
-void test_returning_move_only_type()
-{
- auto move_only_async =
- [](bool x) -> std::experimental::task<std::unique_ptr<int>> {
- if (x) {
- auto p = std::make_unique<int>(123);
- co_return p; // Should be implicit std::move(p) here.
- }
-
- co_return std::make_unique<int>(456);
- };
-
- assert(*sync_wait(move_only_async(true)) == 123);
- assert(*sync_wait(move_only_async(false)) == 456);
-}
-
-void test_co_return_with_curly_braces()
-{
- auto t = []() -> std::experimental::task<std::tuple<int, std::string>>
- {
- co_return { 123, "test" };
- }();
-
- auto result = sync_wait(std::move(t));
-
- assert(std::get<0>(result) == 123);
- assert(std::get<1>(result) == "test");
-}
-
-void test_co_return_by_initialiser_list()
-{
- auto t = []() -> std::experimental::task<std::vector<int>>
- {
- co_return { 2, 10, -1 };
- }();
-
- auto result = sync_wait(std::move(t));
-
- assert(result.size() == 3);
- assert(result[0] == 2);
- assert(result[1] == 10);
- assert(result[2] == -1);
-}
-
-int main()
-{
- test_returning_move_only_type();
- test_co_return_with_curly_braces();
- test_co_return_by_initialiser_list();
-
- return 0;
-}
diff --git a/test/std/experimental/task/task.basic/task_of_void.pass.cpp b/test/std/experimental/task/task.basic/task_of_void.pass.cpp
deleted file mode 100644
index de860b5..0000000
--- a/test/std/experimental/task/task.basic/task_of_void.pass.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03, c++11, c++14
-
-#include <experimental/task>
-#include "../manual_reset_event.hpp"
-#include "../sync_wait.hpp"
-
-#include <optional>
-#include <thread>
-
-namespace coro = std::experimental::coroutines_v1;
-
-static bool has_f_executed = false;
-
-static coro::task<void> f()
-{
- has_f_executed = true;
- co_return;
-}
-
-static void test_coroutine_executes_lazily()
-{
- coro::task<void> t = f();
- assert(!has_f_executed);
- coro::sync_wait(t);
- assert(has_f_executed);
-}
-
-static std::optional<int> last_value_passed_to_g;
-
-static coro::task<void> g(int a)
-{
- last_value_passed_to_g = a;
- co_return;
-}
-
-void test_coroutine_accepts_arguments()
-{
- auto t = g(123);
- assert(!last_value_passed_to_g);
- coro::sync_wait(t);
- assert(last_value_passed_to_g);
- assert(*last_value_passed_to_g == 123);
-}
-
-int shared_value = 0;
-int read_value = 0;
-
-coro::task<void> consume_async(manual_reset_event& event)
-{
- co_await event;
- read_value = shared_value;
-}
-
-void produce(manual_reset_event& event)
-{
- shared_value = 101;
- event.set();
-}
-
-void test_async_completion()
-{
- manual_reset_event e;
- std::thread t1{ [&e]
- {
- sync_wait(consume_async(e));
- }};
-
- assert(read_value == 0);
-
- std::thread t2{ [&e] { produce(e); }};
-
- t1.join();
-
- assert(read_value == 101);
-
- t2.join();
-}
-
-int main()
-{
- test_coroutine_executes_lazily();
- test_coroutine_accepts_arguments();
- test_async_completion();
-
- return 0;
-}
diff --git a/test/std/experimental/task/task.lifetime/task_parameter_lifetime.pass.cpp b/test/std/experimental/task/task.lifetime/task_parameter_lifetime.pass.cpp
deleted file mode 100644
index bc1bd43..0000000
--- a/test/std/experimental/task/task.lifetime/task_parameter_lifetime.pass.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03, c++11, c++14
-
-#include <experimental/task>
-#include <cassert>
-
-#include "../counted.hpp"
-#include "../sync_wait.hpp"
-
-DEFINE_COUNTED_VARIABLES();
-
-void test_parameter_lifetime()
-{
- counted::reset();
-
- auto f = [](counted c) -> std::experimental::task<std::size_t>
- {
- co_return c.id();
- };
-
- {
- auto t = f({});
-
- assert(counted::active_instance_count() == 1);
- assert(counted::copy_constructor_count() == 0);
- assert(counted::move_constructor_count() <= 2); // Ideally <= 1
-
- auto id = sync_wait(t);
- assert(id == 1);
-
- assert(counted::active_instance_count() == 1);
- assert(counted::copy_constructor_count() == 0);
-
- // We are relying on C++17 copy-elision when passing the temporary counter
- // into f(). Then f() must move the parameter into the coroutine frame by
- // calling the move-constructor. This move could also potentially be
- // elided by the
- assert(counted::move_constructor_count() <= 1);
- }
-
- assert(counted::active_instance_count() == 0);
-}
-
-int main()
-{
- test_parameter_lifetime();
- return 0;
-}
diff --git a/test/std/experimental/task/task.lifetime/task_return_value_lifetime.pass.cpp b/test/std/experimental/task/task.lifetime/task_return_value_lifetime.pass.cpp
deleted file mode 100644
index cf528f5..0000000
--- a/test/std/experimental/task/task.lifetime/task_return_value_lifetime.pass.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03, c++11, c++14
-
-#include <experimental/task>
-#include <cassert>
-#include <iostream>
-
-#include "../counted.hpp"
-#include "../sync_wait.hpp"
-
-DEFINE_COUNTED_VARIABLES();
-
-void test_return_value_lifetime()
-{
- counted::reset();
-
- auto f = [](bool x) -> std::experimental::task<counted>
- {
- if (x) {
- counted c;
- co_return std::move(c);
- }
- co_return {};
- };
-
- {
- auto t = f(true);
-
- assert(counted::active_instance_count() == 0);
- assert(counted::copy_constructor_count() == 0);
- assert(counted::move_constructor_count() == 0);
-
- {
- auto c = sync_wait(std::move(t));
- assert(c.id() == 1);
-
- assert(counted::active_instance_count() == 2);
- assert(counted::copy_constructor_count() == 0);
- assert(counted::move_constructor_count() > 0);
- assert(counted::default_constructor_count() == 1);
- }
-
- // The result value in 't' is still alive until 't' destructs.
- assert(counted::active_instance_count() == 1);
- }
-
- assert(counted::active_instance_count() == 0);
-
- counted::reset();
-
- {
- auto t = f(false);
-
- assert(counted::active_instance_count() == 0);
- assert(counted::copy_constructor_count() == 0);
- assert(counted::move_constructor_count() == 0);
-
- {
- auto c = sync_wait(std::move(t));
- assert(c.id() == 1);
-
- assert(counted::active_instance_count() == 2);
- assert(counted::copy_constructor_count() == 0);
- assert(counted::move_constructor_count() > 0);
- assert(counted::default_constructor_count() == 1);
- }
-
- // The result value in 't' is still alive until 't' destructs.
- assert(counted::active_instance_count() == 1);
- }
-}
-
-int main()
-{
- test_return_value_lifetime();
- return 0;
-}