Skip to content

Commit

Permalink
Safer awaitables for generators
Browse files Browse the repository at this point in the history
  • Loading branch information
gershnik committed Dec 14, 2023
1 parent adbac9b commit 3f7e790
Showing 1 changed file with 36 additions and 16 deletions.
52 changes: 36 additions & 16 deletions include/objc-helpers/CoDispatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,40 @@ inline namespace CO_DISPATCH_NS {

class Iterator {
friend DispatchGenerator;
private:
struct FirstAwaitable {
Util::ClientAbandonPtr<Promise> m_promise;
Util::QueueHolder m_queue;

void operator co_await() & = delete;
void operator co_await() const & = delete;
auto operator co_await() && noexcept {
struct awaiter : AwaiterBase {
Util::QueueHolder queue;
auto await_resume() noexcept(noexcept(AwaiterBase::promise->getValueToken())) -> Iterator {
return Iterator(std::move(AwaiterBase::promise), queue, AwaiterBase::promise->getValueToken());
}
};
return awaiter{{std::move(m_promise)}, Util::QueueHolder{m_queue}};
};
};
struct NextAwaitable {
Util::ClientAbandonPtr<Promise> promise;
Iterator * __nonnull it;

void operator co_await() & = delete;
void operator co_await() const & = delete;
auto operator co_await() && noexcept {
struct awaiter : AwaiterBase {
Iterator * __nonnull it;
void await_resume() noexcept(noexcept(it->m_promise->getValueToken())) {
it->m_promise = std::move(AwaiterBase::promise);
it->m_valueToken = it->m_promise->getValueToken();
}
};
return awaiter{{std::move(promise)}, it};
}
};
public:
Iterator(Iterator && src) noexcept = default;

Expand All @@ -980,14 +1014,7 @@ inline namespace CO_DISPATCH_NS {
auto next() noexcept {
m_valueToken = nullptr;
m_promise->resumeExecution(m_queue);
struct awaiter : AwaiterBase {
Iterator * me;
void await_resume() noexcept(noexcept(me->m_promise->getValueToken())) {
me->m_promise = std::move(AwaiterBase::promise);
me->m_valueToken = me->m_promise->getValueToken();
}
};
return awaiter{{std::move(m_promise)}, this};
return NextAwaitable{{std::move(m_promise)}, this};
}
operator bool() const noexcept {
return m_valueToken;
Expand All @@ -1006,14 +1033,7 @@ inline namespace CO_DISPATCH_NS {

auto beginOn(dispatch_queue_t __nullable queue) && noexcept {
m_promise->resumeExecution(queue);
struct awaiter : AwaiterBase {
Util::QueueHolder queue;

auto await_resume() noexcept(noexcept(AwaiterBase::promise->getValueToken())) -> Iterator {
return Iterator(std::move(AwaiterBase::promise), queue, AwaiterBase::promise->getValueToken());
}
};
return awaiter{{std::move(m_promise)}, Util::QueueHolder{queue}};
return typename Iterator::FirstAwaitable{{std::move(m_promise)}, Util::QueueHolder{queue}};
}

auto begin() && noexcept
Expand Down

0 comments on commit 3f7e790

Please sign in to comment.