12 using ValueStorage = std::conditional_t<std::is_lvalue_reference_v<T>, std::add_pointer_t<T>, std::optional<T>>;
15 std::coroutine_handle<> handle;
17 std::binary_semaphore sem{0};
18 std::atomic_bool finished{
false};
21 if constexpr (std::is_lvalue_reference_v<T>) {
28 if (
auto h = exchange(handle,
nullptr)) {
34 std::shared_ptr<Data> data;
38 std::shared_ptr<Data> data;
48 bool finished()
const {
return data->finished; }
49 void finish()
const { data->finished.store(
true); }
51 template <
class... Args>
52 requires(!std::is_lvalue_reference_v<T>)
53 constexpr void emplace(Args&&... args)
const {
55 data->value.emplace(std::forward<Args>(args)...);
59 constexpr void emplace(T& t)
const
60 requires(std::is_lvalue_reference_v<T>)
63 data->value = std::addressof(t);
76 std::shared_ptr<Data> data;
82 IncAwaiter(
Iterator& iter) : iter(iter) {}
84 constexpr bool await_ready()
const noexcept {
return iter.data ==
nullptr || iter.data->finished; }
85 void await_suspend(std::coroutine_handle<> handle) {
86 iter.data->handle = handle;
88 iter.data->sem.release();
90 constexpr Iterator& await_resume()
const noexcept {
91 if (iter.data && iter.data->finished && !iter.data->value) {
107 [[nodiscard]] IncAwaiter operator++() {
return IncAwaiter{*
this}; }
109 [[nodiscard]]
bool operator==(
Iterator const& other)
const noexcept {
return data == other.data; }
111 [[nodiscard]]
bool operator==(std::nullptr_t)
const noexcept {
return data ==
nullptr; }
113 [[nodiscard]]
operator bool()
const noexcept {
return data !=
nullptr; }
115 [[nodiscard]] T&& operator*()
const noexcept {
return static_cast<T&&
>(*data->value); }
117 [[nodiscard]] std::add_pointer_t<T> operator->()
const noexcept {
return std::addressof(*data->value); }
121 data->finished.store(
true);
134 ValueSetter getValueSetter()
const {
return ValueSetter{*
this}; }
136 [[nodiscard]] Iterator end() noexcept {
return {}; }
138 [[nodiscard]]
auto begin() noexcept {
140 CallbackTransformer& ct;
143 BeginAwaiter(CallbackTransformer& ct) : ct(ct) {}
145 constexpr bool await_ready() const noexcept {
return ct.data->finished; }
146 void await_suspend(std::coroutine_handle<> handle) {
147 ct.data->handle = handle;
148 ct.data->sem.release();
150 constexpr Iterator await_resume() const noexcept {
151 if (ct.data->finished && !ct.data->value) {
156 constexpr void setExecutor(ExecutorRef ex) { ct.data->exec = ex; }
158 return BeginAwaiter{*
this};
161 ~CallbackTransformer() {
163 data->finished.store(
true);