From 47d20f2507e2ecaa4e54901e368e4f65afaceaae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8E=E6=B4=AA=E6=B4=8B?= <97099566+yhy0816@users.noreply.github.com> Date: Wed, 9 Oct 2024 20:30:04 +0800 Subject: [PATCH 1/6] =?UTF-8?q?Update=2005=E5=86=85=E5=AD=98=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E4=B8=8E=E5=8E=9F=E5=AD=90=E6=93=8D=E4=BD=9C.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 拼写错误 Signed-off-by: 于洪洋 <97099566+yhy0816@users.noreply.github.com> --- ...70\216\345\216\237\345\255\220\346\223\215\344\275\234.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/md/05\345\206\205\345\255\230\346\250\241\345\236\213\344\270\216\345\216\237\345\255\220\346\223\215\344\275\234.md" "b/md/05\345\206\205\345\255\230\346\250\241\345\236\213\344\270\216\345\216\237\345\255\220\346\223\215\344\275\234.md" index 94e41e85..1b576d77 100644 --- "a/md/05\345\206\205\345\255\230\346\250\241\345\236\213\344\270\216\345\216\237\345\255\220\346\223\215\344\275\234.md" +++ "b/md/05\345\206\205\345\255\230\346\250\241\345\236\213\344\270\216\345\216\237\345\255\220\346\223\215\344\275\234.md" @@ -228,7 +228,7 @@ struct trivial_type { > > 最后强调一下:任何 [std::atomic](https://zh.cppreference.com/w/cpp/atomic/atomic) 类型,**初始化不是原子操作**。 -### `st::atomic_flag` +### `std::atomic_flag` `std::atomic_flag` 是最简单的原子类型,这个类型的对象可以在两个状态间切换:**设置(true)**和**清除(false)**。它很简单,通常只是用作构建一些库设施,不会单独使用或直接面向普通开发者。 @@ -815,4 +815,4 @@ RISC-V 采用的也是**弱序内存模型**(weakly-ordered memory model), \ No newline at end of file +--> From 7a53541a5b86c172fd0215e7d4487ab23c9b6fbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mq=E7=99=BD?= <3326284481@qq.com> Date: Sun, 13 Oct 2024 14:48:14 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E5=88=A0=E9=99=A4=20Gitbook=20=E6=97=A0?= =?UTF-8?q?=E6=84=8F=E4=B9=89=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AF=BE=E7=A8=8B=E9=93=BE=E6=8E=A5=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=83=A8=E5=88=86=E5=8D=8F=E7=A8=8B=E5=89=8D?= =?UTF-8?q?=E8=A8=80=E6=8F=8F=E8=BF=B0=EF=BC=88=E8=BF=98=E9=9C=80=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=8C=E6=97=A0=E5=A4=AA=E5=A4=9A=E4=BB=B7=E5=80=BC?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- SUMMARY.md | 14 -------------- "md/06\345\215\217\347\250\213.md" | 18 ++++++++++++++++-- 3 files changed, 17 insertions(+), 17 deletions(-) delete mode 100644 SUMMARY.md diff --git a/README.md b/README.md index 02ddaf23..415527f9 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ # 现代C++并发编程教程 -本仓库用来存放 B 站课程[《现代 C++ 并发编程教程》]()的教案、代码。 +本仓库用来存放 B 站课程[《现代 C++ 并发编程教程》](https://www.bilibili.com/cheese/play/ss34184)的教案、代码。 不管是否购买课程,任何组织和个人遵守 [CC BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh-hans) 协议均可随意使用学习。 diff --git a/SUMMARY.md b/SUMMARY.md deleted file mode 100644 index cb06bc84..00000000 --- a/SUMMARY.md +++ /dev/null @@ -1,14 +0,0 @@ -# Summary - -* [首页](README.md) -* [阅读须知](md/README.md) -* [基本概念](md/01基本概念.md) -* [使用线程](md/02使用线程.md) -* [共享数据](md/03共享数据.md) -* [同步操作](md/04同步操作.md) -* [内存模型与原子操作](md/05内存模型与原子操作.md) -* [协程](md/06协程.md) -* [详细分析](md/详细分析/README.md) - * [`std::thread` 的构造-源码解析](md/详细分析/01thread的构造与源码解析.md) - * [`std::scoped_lock` 的源码实现与解析](md/详细分析/02scoped_lock源码解析.md) - * [`std::async` 与 `std::future` 源码解析](md/详细分析/03async与future源码解析.md) diff --git "a/md/06\345\215\217\347\250\213.md" "b/md/06\345\215\217\347\250\213.md" index e696832f..eeb2e994 100644 --- "a/md/06\345\215\217\347\250\213.md" +++ "b/md/06\345\215\217\347\250\213.md" @@ -1,9 +1,23 @@ # 协程 +## 前言 + 既然是“**现代**” C++ 并发编程教程,怎么能不聊协程呢? C++20 引入了协程语法,新增了三个用作协程的关键字:`co_await`、`co_yield`、`co_return`。但并未给出标准**协程库**,协程库在 C++23 被引入。 -希望您拥有 `gcc14`、`clang18`,最新的 MSVC。 +希望您拥有 `gcc14`、`clang19`,`Visual Studio 2022 17.11`。 + +我们假设您对 C++20 的协程一无所知、假设您对协程这个概念一无所知、假设您不了解其它语言的协程实现(如 Python、java)。 + +--- + +绝大多数人对协程基本可以说是一无所知,但是应该都听过这个名字,大概是因为这些编程语言都在新版本中引入它作为核心语言特性。 + +这带来了许多的热度,不过这并不完全算是好事,许多的营销号一样的讲述,基本全部都是错误的。 + +据我所知,在我在 B站发布正经 C++20 协程的教学视频之前,几乎所有打着 C++ 旗号说什么协程的,都是胡言乱语。不过也有一些不错的,如:[**等疾风**](https://space.bilibili.com/35186937)、[**happyyang的百草园**](https://space.bilibili.com/312883756),都出过至少算作正经的 C++20 协程的教学视频。 + +- **C++20 的协程是复杂的**。 -> C++ 20 协程的使用尚不成熟,等待后续更新讲解..... +不管是使用上还是概念上,引入了许多新颖的做法。 From a83aeecb0d45ccab3db2dfd13cb27c7556086d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mq=E7=99=BD?= <3326284481@qq.com> Date: Wed, 16 Oct 2024 20:56:38 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20`{}`=20=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E5=8F=AF=E8=83=BD=E5=AF=BC=E8=87=B4=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E7=9A=84=E4=BB=A3=E7=A0=81=EF=BC=8C=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E3=80=82fixes=20#36?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "md/02\344\275\277\347\224\250\347\272\277\347\250\213.md" | 4 ++-- "md/04\345\220\214\346\255\245\346\223\215\344\275\234.md" | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git "a/md/02\344\275\277\347\224\250\347\272\277\347\250\213.md" "b/md/02\344\275\277\347\224\250\347\272\277\347\250\213.md" index ef2d5342..798596db 100644 --- "a/md/02\344\275\277\347\224\250\347\272\277\347\250\213.md" +++ "b/md/02\344\275\277\347\224\250\347\272\277\347\250\213.md" @@ -91,7 +91,7 @@ auto sum(ForwardIt first, ForwardIt last){ std::size_t remainder = distance % num_threads; // 存储每个线程的结果 - std::vector results { num_threads }; + std::vector results(num_threads); // 存储关联线程的线程对象 std::vector threads; @@ -120,7 +120,7 @@ auto sum(ForwardIt first, ForwardIt last){ } ``` -> [运行](https://godbolt.org/z/MdrP98o13)测试。 +> [运行](https://godbolt.org/z/9qW55aY6j)测试。 我们写了这样一个求和函数 `sum`,接受两个迭代器计算它们范围中对象的和。 diff --git "a/md/04\345\220\214\346\255\245\346\223\215\344\275\234.md" "b/md/04\345\220\214\346\255\245\346\223\215\344\275\234.md" index 74f89d78..b428dcbe 100644 --- "a/md/04\345\220\214\346\255\245\346\223\215\344\275\234.md" +++ "b/md/04\345\220\214\346\255\245\346\223\215\344\275\234.md" @@ -697,9 +697,9 @@ auto sum(ForwardIt first, ForwardIt last) { std::size_t remainder = distance % num_threads; // 存储每个线程要执行的任务 - std::vector>tasks; + std::vector> tasks; // 和每一个任务进行关联的 future 用于获取返回值 - std::vector>futures(num_threads); + std::vector> futures(num_threads); // 存储关联线程的线程对象 std::vector threads; @@ -733,7 +733,7 @@ auto sum(ForwardIt first, ForwardIt last) { } ``` -> [运行](https://godbolt.org/z/r19MYcv6e)测试。 +> [运行](https://godbolt.org/z/79fe1Gvcq)测试。 相比于之前,其实不同无非是定义了 `std::vector> tasks` 与 `std::vector> futures` ,然后在循环中制造任务插入容器,关联 future,再放到线程中执行。最后汇总的时候写一个循环,`futures[i].get()` 获取任务的返回值加起来即可。 From c44abef6021a1e4ac3746d69f3237fc0c910c508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mq=E7=99=BD?= <3326284481@qq.com> Date: Sat, 19 Oct 2024 13:49:19 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=AC=AC=E5=9B=9B?= =?UTF-8?q?=E7=AB=A0=EF=BC=9A=E5=88=A0=E9=99=A4=E9=87=8D=E5=A4=8D=E6=8F=8F?= =?UTF-8?q?=E8=BF=B0=EF=BC=8C=E4=BF=AE=E6=94=B9=20`SFML`=20=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E9=85=8D=E7=BD=AE=E7=9A=84=E8=A1=A5=E5=85=85=E6=8E=AA?= =?UTF-8?q?=E8=BE=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "md/04\345\220\214\346\255\245\346\223\215\344\275\234.md" | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git "a/md/04\345\220\214\346\255\245\346\223\215\344\275\234.md" "b/md/04\345\220\214\346\255\245\346\223\215\344\275\234.md" index b428dcbe..85e001f0 100644 --- "a/md/04\345\220\214\346\255\245\346\223\215\344\275\234.md" +++ "b/md/04\345\220\214\346\255\245\346\223\215\344\275\234.md" @@ -371,12 +371,11 @@ private: 该代码实现了一个简单的**后台音频播放类型**,通过**条件变量**和**互斥量**确保播放线程 `playMusic` 只在只在**有音频任务需要播放时工作**(当外部通过调用 `addAudioPath()` 向队列添加播放任务时)。在没有任务时,线程保持等待状态,避免占用 CPU 资源影响主程序的运行。 > ### 注意 +> > 其实这段代码还存在着一个初始化顺序导致的问题,见 [**#27**](https://github.com/Mq-b/ModernCpp-ConcurrentProgramming-Tutorial/issues/27) 此外,关于提示音的播报,为了避免每次都手动添加路径,我们可以创建一个音频资源数组,便于使用: -此外,关于提示音的播报,为了避免每次都手动添加路径,我们可以创建一个音频资源数组,便于使用: - ```cpp static constexpr std::array soundResources{ "./sound/01初始化失败.ogg", @@ -416,8 +415,8 @@ enum SoundIndex { 如果是测试使用,不知道去哪生成这些语音播报,我们推荐 [`tts-vue`](https://github.com/LokerL/tts-vue)。 -> 我们的代码也可以在 Linux 中运行,并且整体仅需 C++11 标准,除了 `soundResources` 数组以外。 -> SFML 依赖于 [**FLAC**](https://xiph.org/flac/) 和 [**OpenAL**](https://www.openal.org/) 这两个库。在 Windows 上[下载](https://www.sfml-dev.org/download/sfml/2.5.1/)的 SFML 版本已包含这些依赖,但在 Linux 上需要用户自行下载并安装它们。如: +> 我们的代码也可以在 Linux 中运行,并且整体仅需 C++11 标准(除了 `soundResources` 数组)。 +> SFML 依赖于 [**FLAC**](https://xiph.org/flac/) 和 [**OpenAL**](https://www.openal.org/) 这两个库。官网上[下载](https://www.sfml-dev.org/download/sfml/2.5.1/)的 windows 版本的 SFML 已包含这些依赖,但在 Linux 上需要用户自行下载并安装它们。如: > ```shell > sudo apt-get install libflac-dev > sudo apt-get install libopenal-dev From 0c78a47eb9944f521a18c655a7003d7f19cd6049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mq=E7=99=BD?= <3326284481@qq.com> Date: Mon, 28 Oct 2024 21:57:44 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20CMakeList=EF=BC=8C?= =?UTF-8?q?=E5=BC=95=E5=85=A5`cpp-terminal`=20=E4=B8=8E=20`spdlog`?= =?UTF-8?q?=E3=80=82=E7=BC=96=E5=86=99=20`spdlog`=20=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=20`Log.h`=20=EF=BC=8C=E8=BF=98=E9=9C=80?= =?UTF-8?q?=E6=94=B9=E8=BF=9B=E3=80=82=20=E5=90=8E=E7=BB=AD=E8=80=83?= =?UTF-8?q?=E8=99=91=E7=BC=96=E5=86=99=E8=AF=A6=E7=BB=86=E7=9A=84=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E6=96=87=E6=A1=A3=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CMakeLists.txt | 18 +++++++++++- .../Log.h | 29 +++++++++++++++++++ .../test2.cpp | 13 +++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 code/ModernCpp-ConcurrentProgramming-Tutorial/Log.h create mode 100644 code/ModernCpp-ConcurrentProgramming-Tutorial/test2.cpp diff --git a/code/ModernCpp-ConcurrentProgramming-Tutorial/CMakeLists.txt b/code/ModernCpp-ConcurrentProgramming-Tutorial/CMakeLists.txt index 7f2eafa3..a007c256 100644 --- a/code/ModernCpp-ConcurrentProgramming-Tutorial/CMakeLists.txt +++ b/code/ModernCpp-ConcurrentProgramming-Tutorial/CMakeLists.txt @@ -12,7 +12,7 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "C add_compile_options("-finput-charset=UTF-8" "-fexec-charset=UTF-8" "-fopenmp") endif() -add_executable(${PROJECT_NAME} "45原子特化shared_ptr.cpp") +add_executable(${PROJECT_NAME} "test2.cpp") set(SFML_DIR "D:/lib/SFML-2.6.1-windows-vc17-64-bit/SFML-2.6.1/lib/cmake/SFML") find_package(SFML 2.6.1 COMPONENTS system window graphics audio network REQUIRED) @@ -30,3 +30,19 @@ set(Boost_INCLUDE_DIR "D:/vcpkg-master/installed/x64-windows/include") include_directories(${Boost_INCLUDE_DIR}) find_package(Boost REQUIRED COMPONENTS system) target_link_libraries(${PROJECT_NAME} PRIVATE Boost::system) + +target_include_directories(${PROJECT_NAME} PRIVATE "D:/project/cpp-terminal/include") +if(CMAKE_BUILD_TYPE STREQUAL "Release") + target_link_libraries(${PROJECT_NAME} PRIVATE + "D:/project/cpp-terminal/lib/cpp-terminal-private.lib" + "D:/project/cpp-terminal/lib/cpp-terminal.lib" + ) +else() + target_link_libraries(${PROJECT_NAME} PRIVATE + "D:/project/cpp-terminal/lib/private/debug/cpp-terminal-private.lib" + "D:/project/cpp-terminal/lib/debug/cpp-terminal.lib" + ) +endif() + +find_package(spdlog REQUIRED) +target_link_libraries(${PROJECT_NAME} PRIVATE spdlog::spdlog_header_only) diff --git a/code/ModernCpp-ConcurrentProgramming-Tutorial/Log.h b/code/ModernCpp-ConcurrentProgramming-Tutorial/Log.h new file mode 100644 index 00000000..78e152c3 --- /dev/null +++ b/code/ModernCpp-ConcurrentProgramming-Tutorial/Log.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include + +inline void setupLogging() { + auto file_sink = std::make_shared("logs.txt"); + file_sink->set_level(spdlog::level::debug); + file_sink->set_pattern("[%Y-%m-%d %H:%M:%S] [%@] [%!] [thread %t] [%oms] [%l] %v"); + + auto console_sink = std::make_shared(); + console_sink->set_level(spdlog::level::debug); + console_sink->set_pattern("%^[%Y-%m-%d %H:%M:%S] [thread %t] [%oms] [%l] %v%$"); + + auto logger = std::make_shared("multi_sink", spdlog::sinks_init_list{ file_sink, console_sink }); + spdlog::register_logger(logger); + + spdlog::set_default_logger(logger); +} + +// spdlog 要想输出文件、路径、函数、行号,只能借助此宏,才会显示。 +// 其实使用 C++20 std::source_location 也能获取这些信息,后面再考虑单独封装吧,目前这样做导致没办法做格式字符串。 + +#define LOG_INFO(msg, ...) SPDLOG_LOGGER_INFO(spdlog::get("multi_sink"), msg) +#define LOG_WARN(msg, ...) SPDLOG_LOGGER_WARN(spdlog::get("multi_sink"), msg) +#define LOG_ERROR(msg, ...) SPDLOG_LOGGER_ERROR(spdlog::get("multi_sink"), msg) + +const auto init_log = (setupLogging(), 0); diff --git a/code/ModernCpp-ConcurrentProgramming-Tutorial/test2.cpp b/code/ModernCpp-ConcurrentProgramming-Tutorial/test2.cpp new file mode 100644 index 00000000..b9266883 --- /dev/null +++ b/code/ModernCpp-ConcurrentProgramming-Tutorial/test2.cpp @@ -0,0 +1,13 @@ +#include "Log.h" +#include +#include +using namespace std::chrono_literals; + +int main() { + LOG_WARN("😅"); + std::jthread t{[]{ + std::this_thread::sleep_for(100ms); + LOG_ERROR("🤣"); + }}; + LOG_INFO("👉"); +} \ No newline at end of file From c8eca2ab5437a9dc2e3804999c159c390bc5b7ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mq=E7=99=BD?= <3326284481@qq.com> Date: Fri, 1 Nov 2024 19:16:39 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20CMake=20=E5=BA=93?= =?UTF-8?q?=E7=9A=84=E9=85=8D=E7=BD=AE=EF=BC=8C=E6=96=87=E6=A1=A3=E5=8F=82?= =?UTF-8?q?=E8=A7=81=EF=BC=9A=20https://github.com/Mq-b/Loser-HomeWork/blo?= =?UTF-8?q?b/main/src/%E5%8D%A2%E7%91%9F%E6%97%A5%E7%BB%8F/make%E3%80%81cm?= =?UTF-8?q?ake%E3%80%81apt%20%E5%8C%85%E7%AE%A1%E7%90%86%EF%BC%8C%E7%BC%96?= =?UTF-8?q?%E8%AF%91%E9%85%8D%E7%BD%AE%E7%AD%89%E9%97%AE%E9%A2%98.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/ModernCpp-ConcurrentProgramming-Tutorial/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/ModernCpp-ConcurrentProgramming-Tutorial/CMakeLists.txt b/code/ModernCpp-ConcurrentProgramming-Tutorial/CMakeLists.txt index a007c256..94d9567a 100644 --- a/code/ModernCpp-ConcurrentProgramming-Tutorial/CMakeLists.txt +++ b/code/ModernCpp-ConcurrentProgramming-Tutorial/CMakeLists.txt @@ -14,11 +14,11 @@ endif() add_executable(${PROJECT_NAME} "test2.cpp") -set(SFML_DIR "D:/lib/SFML-2.6.1-windows-vc17-64-bit/SFML-2.6.1/lib/cmake/SFML") +set(CMAKE_PREFIX_PATH "D:/lib" CACHE STRING "自定义查找包的安装路径" FORCE) + find_package(SFML 2.6.1 COMPONENTS system window graphics audio network REQUIRED) target_link_libraries(${PROJECT_NAME} PRIVATE sfml-system sfml-window sfml-graphics sfml-audio sfml-network) -set(fmt_DIR "D:/lib/fmt_x64-windows/share/fmt") find_package(fmt CONFIG REQUIRED) target_link_libraries(${PROJECT_NAME} PRIVATE fmt::fmt-header-only)