迁移(未编译通过)。
This commit is contained in:
211
coroutine/main.cpp
Normal file
211
coroutine/main.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/use_future.hpp>
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
|
||||
namespace asio = boost::asio;
|
||||
|
||||
asio::awaitable<int> calculate_value()
|
||||
{
|
||||
asio::steady_timer timer(co_await asio::this_coro::executor);
|
||||
timer.expires_after(std::chrono::seconds(1));
|
||||
|
||||
// 这里的 async_wait 是这样的:
|
||||
// 1. 告诉操作系统:"1秒后叫醒我"
|
||||
// 2. 操作系统内核开始计时
|
||||
// 3. 你的线程继续做其他事
|
||||
// 4. 1秒后,操作系统主动通知你的程序
|
||||
// 所以这里在这 1 秒期间内,不占用任何CPU资源。
|
||||
co_await timer.async_wait(asio::use_awaitable);
|
||||
co_return 42;
|
||||
|
||||
/*
|
||||
2025-12-16 按照我目前的理解,这个
|
||||
协程和线程的底层核心
|
||||
*/
|
||||
}
|
||||
|
||||
asio::awaitable<void> process_task()
|
||||
{
|
||||
try {
|
||||
std::cout << "开始计算...\n";
|
||||
int result = co_await calculate_value(); // 等待子协程
|
||||
std::cout << "计算结果: " << result << "\n";
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "计算错误: " << e.what() << "\n";
|
||||
throw; // 重新抛出,让调用者知道
|
||||
}
|
||||
}
|
||||
|
||||
int test1()
|
||||
{
|
||||
asio::io_context io;
|
||||
|
||||
// 使用 use_future 获取 future
|
||||
// co_spawn 只是安排协程,并无动作和运行。
|
||||
std::future<void> fut = asio::co_spawn(io, process_task(), asio::use_future);
|
||||
|
||||
// 在工作线程中运行 io_context
|
||||
std::thread io_thread([&io]() { io.run(); });
|
||||
|
||||
std::cout << "主线程等待协程完成...\n";
|
||||
|
||||
try {
|
||||
// 等待协程完成
|
||||
fut.get();
|
||||
std::cout << "协程成功完成\n";
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "协程异常: " << e.what() << "\n";
|
||||
}
|
||||
|
||||
io_thread.join();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 这是一个阻塞版本的Worker
|
||||
class Worker
|
||||
{
|
||||
public:
|
||||
Worker() = default;
|
||||
|
||||
bool Run()
|
||||
{
|
||||
isOk_ = false;
|
||||
if (!simulateCal()) {
|
||||
return false;
|
||||
}
|
||||
std::cout << "Done..." << calData_ << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool simulateCal()
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||
calData_ = 12;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool isOk_{};
|
||||
int calData_{};
|
||||
};
|
||||
|
||||
int testRun()
|
||||
{
|
||||
Worker wk;
|
||||
return wk.Run();
|
||||
}
|
||||
|
||||
// 上面阻塞版本的Worker改成协程版本
|
||||
class WorkerCoroutine
|
||||
{
|
||||
public:
|
||||
WorkerCoroutine(asio::io_context& io) : io_(io), pool_(std::thread::hardware_concurrency())
|
||||
{
|
||||
}
|
||||
|
||||
asio::awaitable<bool> Run()
|
||||
{
|
||||
isOk_ = false;
|
||||
bool success = co_await simulateCal();
|
||||
if (!success) {
|
||||
co_return false;
|
||||
}
|
||||
|
||||
std::cout << "Done..." << calData_ << std::endl;
|
||||
isOk_ = true;
|
||||
co_return true;
|
||||
}
|
||||
|
||||
private:
|
||||
asio::awaitable<bool> simulateCal()
|
||||
{
|
||||
// 核心代码在这里
|
||||
// 从这里可以看出,协程只适合能通知唤醒的阻塞,比如 socket.recv 虽然阻塞
|
||||
// 但是可以被 OS 唤醒。不适合直接的阻塞比如 从一个驱动中读取数组,然后驱动很慢有阻塞这种。
|
||||
// 非要用的话,需要把真正的阻塞(不是睡眠那种阻塞而是真正的耗时阻塞,比如计算)包装成异步。
|
||||
|
||||
// 测试可唤醒异步
|
||||
// asio::steady_timer timer(io_);
|
||||
// timer.expires_after(std::chrono::seconds(3));
|
||||
// co_await timer.async_wait(asio::use_awaitable);
|
||||
|
||||
// 测试包装后的真正阻塞
|
||||
// auto f = std::async(std::launch::async, [this]() { return realBlock(); });
|
||||
// 不能这么写。
|
||||
// co_await f.get();
|
||||
|
||||
// auto ex = co_await asio::this_coro::executor;
|
||||
// auto r = co_await asio::co_spawn(io_, readBlockCorouitine, asio::use_awaitable);
|
||||
|
||||
// 这个虽然能执行,但是实际只是因为这里只有一个协程。
|
||||
// co_await readBlockCorouitine();
|
||||
|
||||
bool result = co_await asio::co_spawn(
|
||||
pool_, [this]() -> asio::awaitable<bool> { co_return co_await readBlockCorouitine(); }, asio::use_awaitable);
|
||||
|
||||
calData_ = 12;
|
||||
co_return true;
|
||||
}
|
||||
|
||||
// 真正阻塞的函数
|
||||
bool realBlock()
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||
return true;
|
||||
}
|
||||
|
||||
asio::awaitable<bool> readBlockCorouitine()
|
||||
{
|
||||
std::cout << "模拟耗时开启..." << std::endl;
|
||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||
std::cout << "模拟耗时结束..." << std::endl;
|
||||
co_return true;
|
||||
}
|
||||
|
||||
private:
|
||||
asio::io_context& io_;
|
||||
bool isOk_{};
|
||||
int calData_{};
|
||||
asio::thread_pool pool_;
|
||||
};
|
||||
|
||||
int testRunCoroutine()
|
||||
{
|
||||
asio::io_context io;
|
||||
WorkerCoroutine wk(io);
|
||||
|
||||
// 使用 use_future 获取 future
|
||||
std::future<bool> result_future = asio::co_spawn(io,
|
||||
wk.Run(), // 注意:这里要传 wk.Run() 而不是 wk
|
||||
asio::use_future);
|
||||
|
||||
// 在工作线程运行 io_context
|
||||
std::thread io_thread([&io]() { io.run(); });
|
||||
|
||||
std::cout << "开始异步计算,主线程可以继续...\n";
|
||||
|
||||
bool result = false;
|
||||
try {
|
||||
// 等待异步结果
|
||||
result = result_future.get();
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "协程异常: " << e.what() << "\n";
|
||||
}
|
||||
|
||||
io_thread.join();
|
||||
return result ? 0 : 1; // 返回 0 表示成功
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
#endif
|
||||
|
||||
testRunCoroutine();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user