Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<generator>: Test generator::promise_type #4534

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 22 additions & 19 deletions stl/inc/generator
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,22 @@ struct alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) _Aligned_block {
template <class _Alloc>
concept _Has_real_pointers = same_as<_Alloc, void> || is_pointer_v<typename allocator_traits<_Alloc>::pointer>;

template <class _Allocator = void>
template <class _Allocator>
class _Promise_allocator { // statically specified allocator type
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
private:
using _Alloc = _Rebind_alloc_t<_Allocator, _Aligned_block>;
using _Alloc = _Rebind_alloc_t<_Allocator, _Aligned_block>;
using _Alloc_size_type = allocator_traits<_Alloc>::size_type;

static void* _Allocate(_Alloc _Al, const size_t _Size) {
if constexpr (default_initializable<_Alloc> && allocator_traits<_Alloc>::is_always_equal::value) {
// do not store stateless allocator
const size_t _Count = (_Size + sizeof(_Aligned_block) - 1) / sizeof(_Aligned_block);
return _Al.allocate(_Count);
return _Al.allocate(_Convert_size<_Alloc_size_type>(_Count));
} else {
// store stateful allocator
constexpr size_t _Align = (_STD max)(alignof(_Alloc), sizeof(_Aligned_block));
const size_t _Count = (_Size + sizeof(_Alloc) + _Align - 1) / sizeof(_Aligned_block);
void* const _Ptr = _Al.allocate(_Count);
void* const _Ptr = _Al.allocate(_Convert_size<_Alloc_size_type>(_Count));
const auto _Al_address =
(reinterpret_cast<uintptr_t>(_Ptr) + _Size + alignof(_Alloc) - 1) & ~(alignof(_Alloc) - 1);
::new (reinterpret_cast<void*>(_Al_address)) _Alloc(_STD move(_Al));
Expand Down Expand Up @@ -83,7 +84,7 @@ public:
// make stateless allocator
_Alloc _Al{};
const size_t _Count = (_Size + sizeof(_Aligned_block) - 1) / sizeof(_Aligned_block);
_Al.deallocate(static_cast<_Aligned_block*>(_Ptr), _Count);
_Al.deallocate(static_cast<_Aligned_block*>(_Ptr), static_cast<_Alloc_size_type>(_Count));
} else {
// retrieve stateful allocator
const auto _Al_address =
Expand All @@ -94,7 +95,7 @@ public:

constexpr size_t _Align = (_STD max)(alignof(_Alloc), sizeof(_Aligned_block));
const size_t _Count = (_Size + sizeof(_Alloc) + _Align - 1) / sizeof(_Aligned_block);
_Al.deallocate(static_cast<_Aligned_block*>(_Ptr), _Count);
_Al.deallocate(static_cast<_Aligned_block*>(_Ptr), static_cast<_Alloc_size_type>(_Count));
}
}
};
Expand All @@ -108,7 +109,7 @@ private:
static void __stdcall _Dealloc_stateless(void* const _Ptr, const size_t _Size) noexcept {
_Alloc _Al{};
const size_t _Count = (_Size + sizeof(_Dealloc_fn) + sizeof(_Aligned_block) - 1) / sizeof(_Aligned_block);
_Al.deallocate(static_cast<_Aligned_block*>(_Ptr), _Count);
_Al.deallocate(static_cast<_Aligned_block*>(_Ptr), static_cast<allocator_traits<_Alloc>::size_type>(_Count));
}

template <class _Alloc>
Expand All @@ -123,7 +124,7 @@ private:
_Stored_al.~_Alloc();

const size_t _Count = (_Size + sizeof(_Al) + _Align - 1) / sizeof(_Aligned_block);
_Al.deallocate(static_cast<_Aligned_block*>(_Ptr), _Count);
_Al.deallocate(static_cast<_Aligned_block*>(_Ptr), static_cast<allocator_traits<_Alloc>::size_type>(_Count));
}

static void __stdcall _Dealloc_delete(void* const _Ptr, const size_t _Size) noexcept {
Expand All @@ -132,15 +133,16 @@ private:

template <class _ProtoAlloc>
static void* _Allocate(const _ProtoAlloc& _Proto, size_t _Size) {
using _Alloc = _Rebind_alloc_t<_ProtoAlloc, _Aligned_block>;
auto _Al = static_cast<_Alloc>(_Proto);
using _Alloc = _Rebind_alloc_t<_ProtoAlloc, _Aligned_block>;
using _Alloc_size_type = allocator_traits<_Alloc>::size_type;
auto _Al = static_cast<_Alloc>(_Proto);

if constexpr (default_initializable<_Alloc> && allocator_traits<_Alloc>::is_always_equal::value) {
// don't store stateless allocator
const _Dealloc_fn _Dealloc = _Dealloc_stateless<_Alloc>;

const size_t _Count = (_Size + sizeof(_Dealloc_fn) + sizeof(_Aligned_block) - 1) / sizeof(_Aligned_block);
void* const _Ptr = _Al.allocate(_Count);
void* const _Ptr = _Al.allocate(_Convert_size<_Alloc_size_type>(_Count));
_CSTD memcpy(static_cast<char*>(_Ptr) + _Size, &_Dealloc, sizeof(_Dealloc));
return _Ptr;
} else {
Expand All @@ -150,7 +152,7 @@ private:
const _Dealloc_fn _Dealloc = _Dealloc_stateful<_Alloc>;

const size_t _Count = (_Size + sizeof(_Dealloc_fn) + sizeof(_Al) + _Align - 1) / sizeof(_Aligned_block);
void* const _Ptr = _Al.allocate(_Count);
void* const _Ptr = _Al.allocate(_Convert_size<_Alloc_size_type>(_Count));
_CSTD memcpy(static_cast<char*>(_Ptr) + _Size, &_Dealloc, sizeof(_Dealloc));
_Size += sizeof(_Dealloc_fn);
const auto _Al_address =
Expand Down Expand Up @@ -215,7 +217,7 @@ public:
#ifndef _PREFAST_ // TRANSITION, VSO-1662733
_NODISCARD
#endif // ^^^ no workaround ^^^
suspend_always initial_suspend() noexcept {
suspend_always initial_suspend() const noexcept {
return {};
}

Expand Down Expand Up @@ -443,18 +445,19 @@ private:
static_assert(_Has_real_pointers<_Alloc>, "generator allocators must use raw pointers "
"(N4971 [coro.generator.class]/1.1)");

friend _Gen_promise_base<_Gen_yield_t<_Ref>>;

public:
struct __declspec(empty_bases) promise_type : _Promise_allocator<_Alloc>, _Gen_promise_base<_Gen_yield_t<_Ref>> {
using yielded = _Gen_yield_t<_Ref>;
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved

friend _Gen_promise_base<yielded>;

struct __declspec(empty_bases) promise_type : _Promise_allocator<_Alloc>, _Gen_promise_base<yielded> {
_NODISCARD generator get_return_object() noexcept {
return generator{_Gen_secret_tag{}, coroutine_handle<promise_type>::from_promise(*this)};
}
};
_STL_INTERNAL_STATIC_ASSERT(is_standard_layout_v<promise_type>);
#ifdef __cpp_lib_is_pointer_interconvertible // TRANSITION, LLVM-48860
_STL_INTERNAL_STATIC_ASSERT(
is_pointer_interconvertible_base_of_v<_Gen_promise_base<_Gen_yield_t<_Ref>>, promise_type>);
_STL_INTERNAL_STATIC_ASSERT(is_pointer_interconvertible_base_of_v<_Gen_promise_base<yielded>, promise_type>);
#endif // ^^^ no workaround ^^^

generator(generator&& _That) noexcept : _Coro(_STD exchange(_That._Coro, {})) {}
Expand All @@ -475,7 +478,7 @@ public:
_STL_ASSERT(_Coro, "Can't call begin on moved-from generator");
_Coro.resume();
return typename _Gen_iter_provider<_Value, _Ref>::_Iterator{
_Gen_secret_tag{}, coroutine_handle<_Gen_promise_base<_Gen_yield_t<_Ref>>>::from_address(_Coro.address())};
_Gen_secret_tag{}, coroutine_handle<_Gen_promise_base<yielded>>::from_address(_Coro.address())};
}

_NODISCARD default_sentinel_t end() const noexcept {
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ tests\P2474R2_views_repeat
tests\P2474R2_views_repeat_death
tests\P2494R2_move_only_range_adaptors
tests\P2502R2_generator
tests\P2502R2_generator_promise
tests\P2505R5_monadic_functions_for_std_expected
tests\P2510R3_text_formatting_pointers
tests\P2517R1_apply_conditional_noexcept
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P2502R2_generator_promise/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
Loading