diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..8d63d3f --- /dev/null +++ b/.clang-format @@ -0,0 +1,20 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +PointerAlignment: Left +AccessModifierOffset: -4 +ReflowComments: true +SpacesBeforeTrailingComments: 3 +AllowShortFunctionsOnASingleLine: None +AllowShortEnumsOnASingleLine: false +BreakBeforeBraces: Custom +BraceWrapping: + AfterFunction: true + AfterClass: true +TabWidth: 4 +ColumnLimit: 130 +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^<.*>' + Priority: 1 + - Regex: '^".*"' + Priority: 2 diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..40557fb --- /dev/null +++ b/.clangd @@ -0,0 +1,12 @@ +Hover: + ShowAKA: Yes +Diagnostics: + UnusedIncludes: None # 禁用未使用头文件提示 + Suppress: [ + anon_type_definition, # 禁用匿名的typedef提示 + unused-variable, # 禁用未使用变量提示 + unused-function, # 禁用未使用函数提示 + unused-includes, + ] + ClangTidy: + Remove: misc-unused-alias-decls diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fe107f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +build/ +.cache/ +.qtcreator/ +.vs +out/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..acaddb2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,147 @@ +{ + "files.autoSave": "onFocusChange", + "editor.fontSize": 14, + "editor.fontFamily": "'Maple Mono NL NF CN Light', 'Maple Mono NL NF CN Light', 'Maple Mono NL NF CN Light'", + "editor.wordWrap": "on", + "terminal.integrated.fontFamily": "'Maple Mono NL NF CN Light'", + "cmake.configureOnOpen": true, + //"C_Cpp.intelliSenseEngine": "disabled", + "cmake.debugConfig": { + "console": "externalTerminal", + "setupCommands": [ + { + "description": "-gdb-set charset utf-8", + "text": "-gdb-set charset UTF-8" + }, + { + "description": "Enable gdb pretty-printing", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + //"visualizerFile": "${workspaceRoot}/.vscode/qt6.natvis", + "args": [ + "uninstall" + ] + }, + "cmake.configureArgs": [ + "-Wno-dev" + ], + "cmake.configureSettings": { + "CMAKE_PREFIX_PATH": "C:\\local\\boost_1_90_0", + }, + "cmake.options.statusBarVisibility": "visible", + "cmake.generator": "Ninja", + "C_Cpp.default.compileCommands": "${workspaceRoot}/build/compile_commands.json", + "C_Cpp.default.cppStandard": "c++17", + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", + "editor.inlayHints.enabled": "off", + "editor.unicodeHighlight.allowedLocales": { + "ja": true, + "zh-hant": true, + "zh-hans": true + }, + "files.associations": { + "*.cfg": "json", + "xstring": "cpp", + "algorithm": "cpp", + "array": "cpp", + "atomic": "cpp", + "cctype": "cpp", + "charconv": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "condition_variable": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "exception": "cpp", + "filesystem": "cpp", + "forward_list": "cpp", + "fstream": "cpp", + "functional": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "iterator": "cpp", + "limits": "cpp", + "list": "cpp", + "locale": "cpp", + "map": "cpp", + "memory": "cpp", + "mutex": "cpp", + "new": "cpp", + "optional": "cpp", + "ostream": "cpp", + "ratio": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "thread": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeinfo": "cpp", + "unordered_map": "cpp", + "utility": "cpp", + "vector": "cpp", + "xfacet": "cpp", + "xhash": "cpp", + "xiosbase": "cpp", + "xlocale": "cpp", + "xlocbuf": "cpp", + "xlocinfo": "cpp", + "xlocmes": "cpp", + "xlocmon": "cpp", + "xlocnum": "cpp", + "xloctime": "cpp", + "xmemory": "cpp", + "xmemory0": "cpp", + "xstddef": "cpp", + "xtr1common": "cpp", + "xtree": "cpp", + "xutility": "cpp", + "bit": "cpp", + "compare": "cpp", + "concepts": "cpp", + "coroutine": "cpp", + "format": "cpp", + "stop_token": "cpp", + "bitset": "cpp", + "complex": "cpp", + "cstdarg": "cpp", + "set": "cpp", + "variant": "cpp", + "expected": "cpp", + "source_location": "cpp", + "regex": "cpp", + "*.in": "cpp", + "deque": "cpp", + "future": "cpp", + "queue": "cpp", + "resumable": "cpp", + "any": "cpp", + "codecvt": "cpp", + "csignal": "cpp", + "cwctype": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "random": "cpp", + "shared_mutex": "cpp", + "cinttypes": "cpp", + "cfenv": "cpp", + "unordered_set": "cpp", + "ranges": "cpp", + "typeindex": "cpp" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8c092ba --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.16) + +project(how_cpp_work LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if (MSVC) + add_compile_options(/utf-8) + add_definitions(-DWIN32_LEAN_AND_MEAN) + add_definitions(-D_WIN32_WINNT=0x0601) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) +endif() + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/) + +add_definitions(-DFMT_HEADER_ONLY) + +set(Boost_NO_WARN_NEW_VERSIONS 1) +set(Boost_USE_STATIC_LIBS ON) +include_directories(${Boost_INCLUDE_DIR}) + +find_package(Boost COMPONENTS filesystem locale) + +# add_executable(how_cpp_work main.cpp read_config.h read_config.cpp exec_cmd.h exec_cmd.cpp) +# target_link_libraries(how_cpp_work PRIVATE ${Boost_LIBRARIES} ntdll) + +add_subdirectory(task) +add_subdirectory(coroutine) \ No newline at end of file diff --git a/coroutine/CMakeLists.txt b/coroutine/CMakeLists.txt new file mode 100644 index 0000000..cd2ad0a --- /dev/null +++ b/coroutine/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.16) + +project(hcw_Coroutine LANGUAGES CXX) +set(CMAKE_CXX_STANDARD 20) + +add_executable(hcw_Coroutine main.cpp) +target_link_libraries(hcw_Coroutine PRIVATE Boost::boost) + +add_executable(hcw_Coroutine2 main2.cpp) +target_link_libraries(hcw_Coroutine2 PRIVATE Boost::boost) \ No newline at end of file diff --git a/coroutine/main.cpp b/coroutine/main.cpp new file mode 100644 index 0000000..c6e9ae4 --- /dev/null +++ b/coroutine/main.cpp @@ -0,0 +1,211 @@ +#include +#include +#include +#include + +namespace asio = boost::asio; + +asio::awaitable 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 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 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 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 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 { 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 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 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; +} \ No newline at end of file diff --git a/coroutine/main2.cpp b/coroutine/main2.cpp new file mode 100644 index 0000000..81779c6 --- /dev/null +++ b/coroutine/main2.cpp @@ -0,0 +1,356 @@ +#include +#include +#include +#include +#include +#include + +namespace asio = boost::asio; + +class WorkerCoroutine +{ +public: + WorkerCoroutine(asio::io_context& io, int id) : id_(id), isOk_(false), calData_(0) + { + } + + ~WorkerCoroutine() + { + std::cout << "Worker " << id_ << " 销毁\n"; + } + + // 注意:这里返回asio::awaitable的引用,避免拷贝 + asio::awaitable Run() + { + std::cout << "Worker " << id_ << " 开始运行, ThreadID:" << std::this_thread::get_id() << "\n"; + + isOk_ = false; + bool success = co_await simulateCal(); + + if (!success) { + std::cout << "Worker " << id_ << " 计算失败\n"; + co_return false; + } + + std::cout << "Worker " << id_ << " 计算完成: " << calData_ << "\n"; + isOk_ = true; + co_return true; + } + + int GetID() const + { + return id_; + } + int GetCalData() const + { + return calData_; + } + bool IsOk() const + { + return isOk_; + } + +private: + asio::awaitable simulateCal() + { + std::cout << "Worker " << id_ << " 模拟计算开始\n"; + + // 模拟一些计算 + calData_ = id_ * 100 + 12; + + // 调用阻塞函数 + co_return co_await readBlockCoroutine(); + } + + // 在协程中执行阻塞操作的正确方式 + asio::awaitable readBlockCoroutine() + { + std::cout << "Worker " << id_ << " 开始阻塞操作 (线程: " << std::this_thread::get_id() << ")\n"; + + // 将阻塞操作转移到线程池执行 + asio::thread_pool pool(1); // 使用独立的线程池 + auto result = co_await asio::co_spawn( + pool, + [this]() -> asio::awaitable { + // 真正的阻塞操作在线程池线程执行 + std::cout << "Worker " << id_ << " 在线程池中执行 (线程: " << std::this_thread::get_id() << ")\n"; + + // 这是阻塞操作 + std::this_thread::sleep_for(std::chrono::seconds(1 + (id_ % 3))); + + std::cout << "Worker " << id_ << " 阻塞操作结束\n"; + co_return true; + }, + asio::use_awaitable); + + pool.join(); // 等待线程池完成 + co_return result; + } + +private: + int id_; + bool isOk_; + int calData_; +}; + +// 版本1: 使用co_spawn启动多个协程 +int testMultipleCoroutinesV1() +{ + std::cout << "\n=== 测试版本1: 使用co_spawn启动多个Worker ===" << std::endl; + + asio::io_context io; + const int num_workers = 3; + + // 创建Worker实例 + std::vector> workers; + for (int i = 0; i < num_workers; ++i) { + workers.push_back(std::make_shared(io, i + 1)); + } + + // 使用vector存储future + std::vector> futures; + + // 启动所有协程 + for (const auto& worker : workers) { + // 注意:这里捕获worker的shared_ptr,确保生命周期 + futures.push_back(asio::co_spawn( + io, + [worker]() -> asio::awaitable { + // 直接调用Run(),不需要再次包装 + co_return co_await worker->Run(); + }, + asio::use_future)); + } + + // 运行io_context + std::thread io_thread([&io]() { + std::cout << "IO线程开始运行\n"; + io.run(); + std::cout << "IO线程结束\n"; + }); + + // 主线程可以继续工作 + std::cout << "主线程继续工作...\n"; + for (int i = 0; i < 3; ++i) { + std::cout << "主线程工作 " << i + 1 << "\n"; + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + + // 等待所有结果 + std::cout << "\n等待Worker结果...\n"; + for (size_t i = 0; i < futures.size(); ++i) { + try { + bool result = futures[i].get(); + std::cout << "Worker " << workers[i]->GetID() << " 结果: " << (result ? "成功" : "失败") + << ", 数据: " << workers[i]->GetCalData() << "\n"; + } catch (const std::exception& e) { + std::cerr << "Worker " << workers[i]->GetID() << " 异常: " << e.what() << "\n"; + } + } + + io.stop(); + io_thread.join(); + + return 0; +} + +// 版本2: 更简单的lambda方式 +int testMultipleCoroutinesV2() +{ + std::cout << "\n\n=== 测试版本2: 直接使用lambda协程 ===" << std::endl; + + asio::io_context io; + const int num_tasks = 5; + + // 存储结果 + std::vector> futures; + std::atomic completed{0}; + + // 启动多个协程任务 + for (int i = 0; i < num_tasks; ++i) { + auto task_id = i + 1; + + // 使用lambda创建协程 + auto task = [task_id]() -> asio::awaitable { + std::cout << "任务 " << task_id << " 开始 (协程线程: " << std::this_thread::get_id() << ")\n"; + + // 模拟异步操作 + asio::steady_timer timer(asio::any_io_executor{}, std::chrono::seconds(1)); + co_await timer.async_wait(asio::use_awaitable); + + // 模拟阻塞操作 + std::cout << "任务 " << task_id << " 执行阻塞操作\n"; + asio::thread_pool pool(1); + co_await asio::co_spawn( + pool, + [task_id]() -> asio::awaitable { + std::this_thread::sleep_for(std::chrono::seconds(task_id % 3 + 1)); + co_return task_id * 100; + }, + asio::use_awaitable); + pool.join(); + + std::cout << "任务 " << task_id << " 完成\n"; + co_return task_id * 100; + }; + + // 启动协程 + futures.push_back(asio::co_spawn(io, task, asio::use_future)); + } + + // 运行io_context + asio::thread_pool io_thread_pool(1); + asio::post(io_thread_pool, [&io]() { io.run(); }); + + // 等待所有任务完成 + std::cout << "\n等待所有任务完成...\n"; + for (int i = 0; i < num_tasks; ++i) { + try { + int result = futures[i].get(); + completed++; + std::cout << "任务 " << (i + 1) << " 返回: " << result << "\n"; + } catch (const std::exception& e) { + std::cerr << "任务 " << (i + 1) << " 异常: " << e.what() << "\n"; + } + } + + io.stop(); + io_thread_pool.join(); + + std::cout << "完成 " << completed << "/" << num_tasks << " 个任务\n"; + return 0; +} + +// 版本3: 使用detached启动(不等待结果) +int testMultipleCoroutinesV3() +{ + std::cout << "\n\n=== 测试版本3: 使用detached启动 ===" << std::endl; + + asio::io_context io; + const int num_tasks = 4; + + std::atomic started{0}; + std::atomic completed{0}; + std::mutex cout_mutex; + + // 启动协程但不等待结果 + for (int i = 0; i < num_tasks; ++i) { + auto task_id = i + 1; + + asio::co_spawn( + io, + [task_id, &started, &completed, &cout_mutex]() -> asio::awaitable { + started++; + { + std::lock_guard lock(cout_mutex); + std::cout << "任务 " << task_id << " 开始\n"; + } + + // 模拟工作 + asio::thread_pool pool(1); + co_await asio::co_spawn( + pool, + [task_id]() -> asio::awaitable { + std::this_thread::sleep_for(std::chrono::seconds(1)); + co_return; + }, + asio::use_awaitable); + pool.join(); + + completed++; + { + std::lock_guard lock(cout_mutex); + std::cout << "任务 " << task_id << " 完成\n"; + } + + co_return; + }, + asio::detached); + } + + // 运行io_context直到所有任务完成 + std::cout << "启动 " << started << " 个任务\n"; + + asio::thread_pool io_pool(2); + asio::post(io_pool, [&io]() { io.run(); }); + + // 等待所有任务完成 + while (completed < num_tasks) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + io.stop(); + io_pool.join(); + + std::cout << "所有 " << completed << " 个任务完成\n"; + return 0; +} + +// 版本4: 修复原始代码中的问题 +int testRunCoroutineFixed() +{ + std::cout << "\n\n=== 修复原始代码 ===" << std::endl; + + asio::io_context io; + + // 创建Worker实例 + WorkerCoroutine wk1(io, 1); + WorkerCoroutine wk2(io, 2); + + // 启动协程 + std::future future1 = + asio::co_spawn(io, [&wk1]() -> asio::awaitable { co_return co_await wk1.Run(); }, asio::use_future); + + std::future future2 = + asio::co_spawn(io, [&wk2]() -> asio::awaitable { co_return co_await wk2.Run(); }, asio::use_future); + + // 运行io_context + asio::thread_pool io_pool(1); + asio::post(io_pool, [&io]() { io.run(); }); + + std::cout << "开始异步计算,主线程可以继续...\n"; + + // 主线程可以继续工作 + for (int i = 0; i < 3; ++i) { + std::cout << "主线程工作 " << i + 1 << "\n"; + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + } + + // 等待结果 + bool result1 = false, result2 = false; + try { + result1 = future1.get(); + std::cout << "Worker1 结果: " << (result1 ? "成功" : "失败") << "\n"; + } catch (const std::exception& e) { + std::cerr << "Worker1 异常: " << e.what() << "\n"; + } + + try { + result2 = future2.get(); + std::cout << "Worker2 结果: " << (result2 ? "成功" : "失败") << "\n"; + } catch (const std::exception& e) { + std::cerr << "Worker2 异常: " << e.what() << "\n"; + } + + io.stop(); + io_pool.join(); + + return (result1 && result2) ? 0 : 1; +} + +int main() +{ +#ifdef _WIN32 + SetConsoleOutputCP(CP_UTF8); +#endif + + std::cout << "=== C++协程多实例测试 ===\n"; + + // 测试各种方式 + testMultipleCoroutinesV1(); + // testMultipleCoroutinesV2(); + // testMultipleCoroutinesV3(); + // testRunCoroutineFixed(); + + return 0; +} \ No newline at end of file diff --git a/task/CMakeLists.txt b/task/CMakeLists.txt new file mode 100644 index 0000000..02a9f6c --- /dev/null +++ b/task/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.16) + +project(hcw_task LANGUAGES CXX) + +add_executable(hcw_task main.cpp) \ No newline at end of file diff --git a/task/main.cpp b/task/main.cpp new file mode 100644 index 0000000..547a79d --- /dev/null +++ b/task/main.cpp @@ -0,0 +1,60 @@ +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +// 1.Promise(生产者)和Future(消费者) +void workTh1(std::promise prom) +{ + std::this_thread::sleep_for(std::chrono::seconds(5)); + prom.set_value(98); +} + +void testTaskTh1() +{ + std::promise prm; + auto fut = prm.get_future(); + + std::thread t(workTh1, std::move(prm)); + + std::cout << "准备打印内容..." << std::endl; + std::cout << fut.get() << std::endl; + std::cout << "打印内容结束..." << std::endl; + + t.join(); +} + +// 2.std::packaged_task本质上是一个包装器, 包装可调用对象,内部使用了std::promise. +int someFunc(int a, int b) +{ + std::this_thread::sleep_for(std::chrono::seconds(3)); + return a + b; +} + +void testTaskTh2() +{ + std::packaged_task pt(someFunc); + auto fut = pt.get_future(); + std::thread t(std::move(pt), 33, 55); + t.join(); + std::cout << __FUNCTION__ << " over, ret = " << fut.get() << std::endl; +} + +// 3.异步运行任务(更高级的用法,不用关心开线程打包这种操作) +void testTaskTh3() +{ + auto fut = std::async(std::launch::async, someFunc, 11, 22); + std::cout << __FUNCTION__ << " over, ret = " << fut.get() << std::endl; +} + +int main() +{ +#ifdef _WIN32 + SetConsoleOutputCP(CP_UTF8); +#endif + testTaskTh3(); + return 0; +} \ No newline at end of file