Skip to content

Commit 46effab

Browse files
Fix <experimental/generator> in /kernel mode (#1373)
Co-authored-by: Curtis J Bezault <[email protected]>
1 parent 1f83628 commit 46effab

File tree

1 file changed

+52
-64
lines changed

1 file changed

+52
-64
lines changed

stl/inc/experimental/generator

Lines changed: 52 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#error <experimental/generator> requires /std:c++latest or /await compiler options
2323
#endif // ^^^ no coroutine support ^^^
2424

25-
2625
#pragma pack(push, _CRT_PACKING)
2726
#pragma warning(push, _STL_WARNING_LEVEL)
2827
#pragma warning(disable : _STL_DISABLED_WARNINGS)
@@ -33,18 +32,16 @@ _STL_DISABLE_CLANG_WARNINGS
3332
_STD_BEGIN
3433

3534
namespace experimental {
36-
37-
template <typename _Ty, typename _Alloc = allocator<char>>
35+
// NOTE WELL: _CPPUNWIND currently affects the ABI of generator.
36+
template <class _Ty, class _Alloc = allocator<char>>
3837
struct generator {
3938
struct promise_type {
40-
_Ty const* _CurrentValue;
41-
#if 1 // TRANSITION, VSO-1172852
42-
#ifdef _CPPUNWIND
43-
exception_ptr _Eptr;
44-
#endif // _CPPUNWIND
39+
const _Ty* _Value;
40+
#ifdef _CPPUNWIND // TRANSITION, VSO-1172852
41+
exception_ptr _Exception;
4542
#endif // TRANSITION, VSO-1172852
4643

47-
auto get_return_object() {
44+
generator get_return_object() noexcept {
4845
return generator{*this};
4946
}
5047

@@ -56,38 +53,38 @@ namespace experimental {
5653
return {};
5754
}
5855

59-
#if defined(_CPPUNWIND) || defined(__cpp_impl_coroutine)
60-
void unhandled_exception() noexcept {
61-
#if 1 // TRANSITION, VSO-1172852
56+
#ifndef _KERNEL_MODE
6257
#ifdef _CPPUNWIND
63-
_Eptr = _STD current_exception();
64-
#else // ^^^ _CPPUNWIND / !_CPPUNWIND vvv
65-
abort();
66-
#endif // _CPPUNWIND
58+
#if 1 // TRANSITION, VSO-1172852
59+
void unhandled_exception() noexcept {
60+
_Exception = _STD current_exception();
61+
}
6762
#else // ^^^ workaround / no workaround vvv
63+
void unhandled_exception() {
6864
throw;
69-
#endif // TRANSITION, VSO-1172852
7065
}
71-
#endif // defined(_CPPUNWIND) || defined(__cpp_impl_coroutine)
66+
#endif // TRANSITION, VSO-1172852
67+
#else // ^^^ defined(_CPPUNWIND) / !defined(_CPPUNWIND) vvv
68+
void unhandled_exception() noexcept {}
69+
#endif // _CPPUNWIND
70+
#endif // _KERNEL_MODE
7271

73-
#if 1 // TRANSITION, VSO-1172852
72+
#ifdef _CPPUNWIND // TRANSITION, VSO-1172852
7473
void _Rethrow_if_exception() {
75-
#ifdef _CPPUNWIND
76-
if (_Eptr) {
77-
_STD rethrow_exception(_Eptr);
74+
if (_Exception) {
75+
_STD rethrow_exception(_Exception);
7876
}
79-
#endif // _CPPUNWIND
8077
}
8178
#endif // TRANSITION, VSO-1172852
8279

83-
auto yield_value(_Ty const& _Value) {
84-
_CurrentValue = _STD addressof(_Value);
85-
return suspend_always{};
80+
suspend_always yield_value(const _Ty& _Val) noexcept {
81+
_Value = _STD addressof(_Val);
82+
return {};
8683
}
8784

88-
void return_void() {}
85+
void return_void() noexcept {}
8986

90-
template <typename _Uty>
87+
template <class _Uty>
9188
_Uty&& await_transform(_Uty&& _Whatever) {
9289
static_assert(_Always_false<_Uty>,
9390
"co_await is not supported in coroutines of type std::experimental::generator");
@@ -98,15 +95,16 @@ namespace experimental {
9895
static_assert(is_same_v<char*, typename allocator_traits<_Alloc_char>::pointer>,
9996
"generator does not support allocators with fancy pointer types");
10097
static_assert(
101-
allocator_traits<_Alloc_char>::is_always_equal::value, "generator only supports stateless allocators");
98+
allocator_traits<_Alloc_char>::is_always_equal::value && is_default_constructible_v<_Alloc_char>,
99+
"generator supports only stateless allocators");
102100

103101
static void* operator new(size_t _Size) {
104-
_Alloc_char _Al;
102+
_Alloc_char _Al{};
105103
return allocator_traits<_Alloc_char>::allocate(_Al, _Size);
106104
}
107105

108106
static void operator delete(void* _Ptr, size_t _Size) noexcept {
109-
_Alloc_char _Al;
107+
_Alloc_char _Al{};
110108
return allocator_traits<_Alloc_char>::deallocate(_Al, static_cast<char*>(_Ptr), _Size);
111109
}
112110
};
@@ -115,21 +113,19 @@ namespace experimental {
115113
using iterator_category = input_iterator_tag;
116114
using difference_type = ptrdiff_t;
117115
using value_type = _Ty;
118-
using reference = _Ty const&;
119-
using pointer = _Ty const*;
116+
using reference = const _Ty&;
117+
using pointer = const _Ty*;
120118

121119
coroutine_handle<promise_type> _Coro = nullptr;
122120

123121
iterator() = default;
124-
iterator(nullptr_t) : _Coro(nullptr) {}
125-
126-
iterator(coroutine_handle<promise_type> _CoroArg) : _Coro(_CoroArg) {}
122+
explicit iterator(coroutine_handle<promise_type> _Coro_) noexcept : _Coro(_Coro_) {}
127123

128124
iterator& operator++() {
129125
_Coro.resume();
130126
if (_Coro.done()) {
131-
#if 1 // TRANSITION, VSO-1172852
132-
_STD exchange(_Coro, {}).promise()._Rethrow_if_exception();
127+
#ifdef _CPPUNWIND // TRANSITION, VSO-1172852
128+
_STD exchange(_Coro, nullptr).promise()._Rethrow_if_exception();
133129
#else // ^^^ workaround / no workaround vvv
134130
_Coro = nullptr;
135131
#endif // TRANSITION, VSO-1172852
@@ -139,61 +135,54 @@ namespace experimental {
139135
}
140136

141137
void operator++(int) {
142-
// This postincrement operator meets the requirements of the Ranges TS
143-
// InputIterator concept, but not those of Standard C++ InputIterator.
138+
// This operator meets the requirements of the C++20 input_iterator concept,
139+
// but not the Cpp17InputIterator requirements.
144140
++*this;
145141
}
146142

147-
_NODISCARD bool operator==(iterator const& _Right) const {
143+
_NODISCARD bool operator==(const iterator& _Right) const noexcept {
148144
return _Coro == _Right._Coro;
149145
}
150146

151-
_NODISCARD bool operator!=(iterator const& _Right) const {
147+
_NODISCARD bool operator!=(const iterator& _Right) const noexcept {
152148
return !(*this == _Right);
153149
}
154150

155-
_NODISCARD reference operator*() const {
156-
return *_Coro.promise()._CurrentValue;
151+
_NODISCARD reference operator*() const noexcept {
152+
return *_Coro.promise()._Value;
157153
}
158154

159-
_NODISCARD pointer operator->() const {
160-
return _Coro.promise()._CurrentValue;
155+
_NODISCARD pointer operator->() const noexcept {
156+
return _Coro.promise()._Value;
161157
}
162158
};
163159

164160
_NODISCARD iterator begin() {
165161
if (_Coro) {
166162
_Coro.resume();
167163
if (_Coro.done()) {
168-
#if 1 // TRANSITION, VSO-1172852
164+
#ifdef _CPPUNWIND // TRANSITION, VSO-1172852
169165
_Coro.promise()._Rethrow_if_exception();
170166
#endif // TRANSITION, VSO-1172852
171-
return {nullptr};
167+
return {};
172168
}
173169
}
174170

175-
return {_Coro};
171+
return iterator{_Coro};
176172
}
177173

178-
_NODISCARD iterator end() {
179-
return {nullptr};
174+
_NODISCARD iterator end() noexcept {
175+
return {};
180176
}
181177

182-
explicit generator(promise_type& _Prom) : _Coro(coroutine_handle<promise_type>::from_promise(_Prom)) {}
178+
explicit generator(promise_type& _Prom) noexcept : _Coro(coroutine_handle<promise_type>::from_promise(_Prom)) {}
183179

184-
generator() = default;
185-
generator(generator const&) = delete;
186-
generator& operator=(generator const&) = delete;
180+
generator() = default;
187181

188-
generator(generator&& _Right) : _Coro(_Right._Coro) {
189-
_Right._Coro = nullptr;
190-
}
182+
generator(generator&& _Right) noexcept : _Coro(_STD exchange(_Right._Coro, nullptr)) {}
191183

192-
generator& operator=(generator&& _Right) {
193-
if (this != _STD addressof(_Right)) {
194-
_Coro = _Right._Coro;
195-
_Right._Coro = nullptr;
196-
}
184+
generator& operator=(generator&& _Right) noexcept {
185+
_Coro = _STD exchange(_Right._Coro, nullptr);
197186
return *this;
198187
}
199188

@@ -206,7 +195,6 @@ namespace experimental {
206195
private:
207196
coroutine_handle<promise_type> _Coro = nullptr;
208197
};
209-
210198
} // namespace experimental
211199

212200
_STD_END

0 commit comments

Comments
 (0)