我从here收集到,协程类型大致分为3类:
generator<> , task<>, and lazy<>
我的问题是:如果要确定返回类型,这三者之间有什么区别?
例如:延迟加载一组文件处理程序的协同例程的返回类是什么?我的实现将使用
task<FileHandler>
和generator<Filehandler>
实现相同目的。我已经在“执行”部分下查看了this,以了解
promise object
与协程进行交互时的限制。但是我只能找到实现上的差异,而不是方法上的差异。
最佳答案
我做了一些研究,我相信答案如下:
首先,C++中没有lazy<>
类。 https://en.cppreference.com/w/cpp/language/coroutines错了。 (请参阅草稿进行确认)
因此,这是generator<T>
和task<T>
的返回类型之间区别的问题。
TLDR;
最容易记住的方法是:
generators
are associated withco_yield
; whereas,tasks
are associated withco_await
生成器
与generator类关联的co_yield机制与我们在python(请参阅文档)中会遇到的机制完全相同,并且与操作系统机制中的
thread_suspend
概念非常相似。您可以选择同步或异步实现。 (有关示例,请引用cppcoro library。)
生成器类型(种类)如下所示:
struct generator {
struct promise_type;
using handle = std::coroutine_handle<promise_type>;
struct promise_type {
int current_value;
static auto get_return_object_on_allocation_failure() { return generator{nullptr}; }
auto get_return_object() { return generator{handle::from_promise(*this)}; }
auto initial_suspend() { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
void unhandled_exception() { std::terminate(); }
void return_void() {}
auto yield_value(int value) {
current_value = value;
return std::suspend_always{};
}
};
bool move_next() { return coro ? (coro.resume(), !coro.done()) : false; }
int current_value() { return coro.promise().current_value; }
generator(generator const&) = delete;
generator(generator && rhs) : coro(rhs.coro) { rhs.coro = nullptr; }
~generator() { if (coro) coro.destroy(); }
private:
generator(handle h) : coro(h) {}
handle coro;
};
您将按以下方式使用生成器类型:generator f() { co_yield 1; co_yield 2; }
任务另一方面,任务与
co_await
表达式关联。它需要Awaitable<T>
和Awaiter<T>
概念,因此请确保您正确使用与这两个概念相关的约束。 Awaiter概念包括以下约束:await_ready
,await_suspend
和await_resume
。可等待的概念有以下限制:(1)co_await
特化/重载和(2)await_transform
不重载。[ref]任务类型如下所示:
class task
{
public:
using promise_type = <unspecified>;
using value_type = T;
task() noexcept;
task(task&& other) noexcept;
task& operator=(task&& other);
task(const task& other) = delete;
task& operator=(const task& other) = delete;
bool is_ready() const noexcept;
Awaiter<T&> operator co_await() const & noexcept;
Awaiter<T&&> operator co_await() const && noexcept;
Awaitable<void> when_ready() const noexcept;
};
您可以选择使用这些概念(最好是我的方法),或者如果您还不熟悉这些概念的存在,那么您可能需要自己实现相关的约束才能实现。使用任务就像[ref]一样简单:
task<> tcp_echo_server() {
char data[1024];
for (;;) {
size_t n = co_await socket.async_read_some(buffer(data));
co_await async_write(socket, buffer(data, n));
}
}
关于c++ - C++:如何正确使用#include <协程>中可用的generator <>,task <>和lazy <>类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64542433/