From 64168e12f03ba362461826d34859c69e1b4eac1b Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sat, 23 Mar 2024 11:58:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=20Github=20=E5=A4=96=E9=83=A8?= =?UTF-8?q?=E4=BB=93=E5=BA=93=E7=9A=84=E4=BB=A3=E7=A0=81=E7=89=87=E6=AE=B5?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=B0=B8=E4=B9=85=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\275\277\347\224\250\347\272\277\347\250\213.md" | 2 +- ...5\205\261\344\272\253\346\225\260\346\215\256.md" | 2 +- ...6\272\220\347\240\201\350\247\243\346\236\220.md" | 12 ++++++------ ...6\272\220\347\240\201\350\247\243\346\236\220.md" | 2 +- 4 files changed, 9 insertions(+), 9 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 7e18da2e..8c1e0d03 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" @@ -477,7 +477,7 @@ void test(){ } ``` - 主线程延时 3 秒,这个传入了一个临时对象 `seconds` ,它是模板 [`std::chrono::duration`](https://zh.cppreference.com/w/cpp/chrono/duration) 的别名,以及还有很多其他的时间类型,都基于这个类。说实话挺麻烦的,如果您支持 C++14,建议使用[时间字面量](https://zh.cppreference.com/w/cpp/symbol_index/chrono_literals),在 [`std::chrono_literals`](https://github.com/microsoft/STL/blob/main/stl/inc/__msvc_chrono.hpp#L742-L804) 命名空间中。我们可以改成下面这样: + 主线程延时 3 秒,这个传入了一个临时对象 `seconds` ,它是模板 [`std::chrono::duration`](https://zh.cppreference.com/w/cpp/chrono/duration) 的别名,以及还有很多其他的时间类型,都基于这个类。说实话挺麻烦的,如果您支持 C++14,建议使用[时间字面量](https://zh.cppreference.com/w/cpp/symbol_index/chrono_literals),在 [`std::chrono_literals`](https://github.com/microsoft/STL/blob/8e2d724cc1072b4052b14d8c5f81a830b8f1d8cb/stl/inc/__msvc_chrono.hpp#L718-L780) 命名空间中。我们可以改成下面这样: ```cpp using namespace std::chrono_literals; diff --git "a/md/03\345\205\261\344\272\253\346\225\260\346\215\256.md" "b/md/03\345\205\261\344\272\253\346\225\260\346\215\256.md" index cf04ed4d..76df2d0c 100644 --- "a/md/03\345\205\261\344\272\253\346\225\260\346\215\256.md" +++ "b/md/03\345\205\261\344\272\253\346\225\260\346\215\256.md" @@ -127,7 +127,7 @@ void f() { } ``` -那么问题来了,`std::lock_guard` 是如何做到的呢?它是怎么实现的呢?首先顾名思义,这是一个“管理类”模板,用来管理互斥量的上锁与解锁,我们来看它的 [MSVC 实现](https://github.com/microsoft/STL/blob/main/stl/inc/mutex#L452-L473): +那么问题来了,`std::lock_guard` 是如何做到的呢?它是怎么实现的呢?首先顾名思义,这是一个“管理类”模板,用来管理互斥量的上锁与解锁,我们来看它的 [MSVC 实现](https://github.com/microsoft/STL/blob/8e2d724cc1072b4052b14d8c5f81a830b8f1d8cb/stl/inc/mutex#L452-L473): ```cpp _EXPORT_STD template diff --git "a/md/\350\257\246\347\273\206\345\210\206\346\236\220/01thread\347\232\204\346\236\204\351\200\240\344\270\216\346\272\220\347\240\201\350\247\243\346\236\220.md" "b/md/\350\257\246\347\273\206\345\210\206\346\236\220/01thread\347\232\204\346\236\204\351\200\240\344\270\216\346\272\220\347\240\201\350\247\243\346\236\220.md" index 93d54934..efcc6e01 100644 --- "a/md/\350\257\246\347\273\206\345\210\206\346\236\220/01thread\347\232\204\346\236\204\351\200\240\344\270\216\346\272\220\347\240\201\350\247\243\346\236\220.md" +++ "b/md/\350\257\246\347\273\206\345\210\206\346\236\220/01thread\347\232\204\346\236\204\351\200\240\344\270\216\346\272\220\347\240\201\350\247\243\346\236\220.md" @@ -2,20 +2,20 @@ 我们这单章是为了专门解释一下 `std::thread` 是如何构造的,是如何创建线程传递参数的,让你彻底了解这个类。 -我们以 **MSVC** 实现的 [`std::thread`](https://github.com/microsoft/STL/blob/main/stl/inc/thread) 代码进行讲解,新版 MSVC STL 的实现完全基于 **C++14**,所以即使是 C++11 引入的标准库设施,实现中可能也是使用到了 C++14 的东西。 +我们以 **MSVC** 实现的 [`std::thread`](https://github.com/microsoft/STL/blob/8e2d724cc1072b4052b14d8c5f81a830b8f1d8cb/stl/inc/thread) 代码进行讲解,新版 MSVC STL 的实现完全基于 **C++14**,所以即使是 C++11 引入的标准库设施,实现中可能也是使用到了 C++14 的东西。 ## `std::thread` 的数据成员 - **了解一个庞大的类,最简单的方式就是先看它的数据成员有什么**。 -`std::thread` 只保有一个私有数据成员 [`_Thr`](https://github.com/microsoft/STL/blob/main/stl/inc/thread#L163): +`std::thread` 只保有一个私有数据成员 [`_Thr`](https://github.com/microsoft/STL/blob/8e2d724cc1072b4052b14d8c5f81a830b8f1d8cb/stl/inc/thread#L163): ```cpp private: _Thrd_t _Thr; ``` -[`_Thrd_t`](https://github.com/microsoft/STL/blob/main/stl/inc/xthreads.h#L22-L26) 是一个结构体,它保有两个数据成员: +[`_Thrd_t`](https://github.com/microsoft/STL/blob/8e2d724cc1072b4052b14d8c5f81a830b8f1d8cb/stl/inc/__msvc_threads_core.hpp#L20-L24) 是一个结构体,它保有两个数据成员: ```cpp using _Thrd_id_t = unsigned int; @@ -47,7 +47,7 @@ struct _Thrd_t { // thread identifier for Win32 thread(thread&& _Other) noexcept : _Thr(_STD exchange(_Other._Thr, {})) {} ``` - [_STD](https://github.com/microsoft/STL/blob/main/stl/inc/yvals_core.h#L1951) 是一个宏,展开就是 `::std::`,也就是 [`::std::exchange`](https://zh.cppreference.com/w/cpp/utility/exchange),将 `_Other._Thr` 赋为 `{}` (也就是置空),返回 `_Other._Thr` 的旧值用以初始化当前对象的数据成员 `_Thr`。 + [_STD](https://github.com/microsoft/STL/blob/8e2d724cc1072b4052b14d8c5f81a830b8f1d8cb/stl/inc/yvals_core.h#L1934) 是一个宏,展开就是 `::std::`,也就是 [`::std::exchange`](https://zh.cppreference.com/w/cpp/utility/exchange),将 `_Other._Thr` 赋为 `{}` (也就是置空),返回 `_Other._Thr` 的旧值用以初始化当前对象的数据成员 `_Thr`。 3. 复制构造函数被定义为弃置的,std::thread 不可复制。两个 std::thread 不可表示一个线程,std::thread 对线程资源是独占所有权。 @@ -68,7 +68,7 @@ struct _Thrd_t { // thread identifier for Win32 前三个构造函数都没啥要特别聊的,非常简单,只有第四个构造函数较为复杂,且是我们本章重点,需要详细讲解。(*注意 MSVC 使用标准库的内容很多时候不加 **std::**,脑补一下就行*) -如你所见,这个构造函数本身并没有做什么,它只是一个可变参数成员函数模板,增加了一些 [SFINAE](https://zh.cppreference.com/w/cpp/language/sfinae) 进行约束我们传入的[可调用](https://zh.cppreference.com/w/cpp/named_req/Callable)对象的类型不能是 `std::thread`。函数体中调用了一个函数 [**`_Start`**](https://github.com/microsoft/STL/blob/main/stl/inc/thread#L72-L87),将我们构造函数的参数全部完美转发,去调用它,这个函数才是我们的重点,如下: +如你所见,这个构造函数本身并没有做什么,它只是一个可变参数成员函数模板,增加了一些 [SFINAE](https://zh.cppreference.com/w/cpp/language/sfinae) 进行约束我们传入的[可调用](https://zh.cppreference.com/w/cpp/named_req/Callable)对象的类型不能是 `std::thread`。函数体中调用了一个函数 [**`_Start`**](https://github.com/microsoft/STL/blob/8e2d724cc1072b4052b14d8c5f81a830b8f1d8cb/stl/inc/thread#L72-L87),将我们构造函数的参数全部完美转发,去调用它,这个函数才是我们的重点,如下: ```cpp template @@ -101,7 +101,7 @@ void _Start(_Fn&& _Fx, _Args&&... _Ax) { 4. `constexpr auto _Invoker_proc = _Get_invoke<_Tuple>(make_index_sequence<1 + sizeof...(_Args)>{})` - - 调用 [`_Get_invoke`](https://github.com/microsoft/STL/blob/main/stl/inc/thread#L65-L68) 函数,传入 `_Tuple` 类型和一个参数序列的索引序列(为了遍历形参包)。这个函数用于获取一个函数指针,指向了一个静态成员函数 [`_Invoke`](https://github.com/microsoft/STL/blob/main/stl/inc/thread#L55-L63),用来实际执行线程。这两个函数都非常的简单,我们来看看: + - 调用 [`_Get_invoke`](https://github.com/microsoft/STL/blob/8e2d724cc1072b4052b14d8c5f81a830b8f1d8cb/stl/inc/thread#L65-L68) 函数,传入 `_Tuple` 类型和一个参数序列的索引序列(为了遍历形参包)。这个函数用于获取一个函数指针,指向了一个静态成员函数 [`_Invoke`](https://github.com/microsoft/STL/blob/8e2d724cc1072b4052b14d8c5f81a830b8f1d8cb/stl/inc/thread#L55-L63),用来实际执行线程。这两个函数都非常的简单,我们来看看: ```cpp template diff --git "a/md/\350\257\246\347\273\206\345\210\206\346\236\220/02scoped_lock\346\272\220\347\240\201\350\247\243\346\236\220.md" "b/md/\350\257\246\347\273\206\345\210\206\346\236\220/02scoped_lock\346\272\220\347\240\201\350\247\243\346\236\220.md" index 1034d2e2..a0cfcf5c 100644 --- "a/md/\350\257\246\347\273\206\345\210\206\346\236\220/02scoped_lock\346\272\220\347\240\201\350\247\243\346\236\220.md" +++ "b/md/\350\257\246\347\273\206\345\210\206\346\236\220/02scoped_lock\346\272\220\347\240\201\350\247\243\346\236\220.md" @@ -4,7 +4,7 @@ 这会涉及到不少的模板技术,这没办法,就如同我们先前聊 [`std::thread` 的构造与源码分析](01thread的构造与源码解析.md)最后说的:“**不会模板,你阅读标准库源码,是无稽之谈**”。 -我们还是一样的,以 MSVC STL 的实现的 [`std::scoped_lock`](https://github.com/microsoft/STL/blob/main/stl/inc/mutex#L476-L528) 代码进行讲解,不用担心,我们也查看了 [`libstdc++`](https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/mutex#L743-L802) 、[`libc++`](https://github.com/llvm/llvm-project/blob/main/libcxx/include/mutex#L424-L488)的实现,并没有太多区别,更多的是一些风格上的。而且个人觉得 MSVC 的实现是最简单直观的。 +我们还是一样的,以 MSVC STL 的实现的 [`std::scoped_lock`](https://github.com/microsoft/STL/blob/8e2d724cc1072b4052b14d8c5f81a830b8f1d8cb/stl/inc/mutex#L476-L528) 代码进行讲解,不用担心,我们也查看了 [`libstdc++`](https://github.com/gcc-mirror/gcc/blob/7a01cc711f33530436712a5bfd18f8457a68ea1f/libstdc%2B%2B-v3/include/std/mutex#L743-L802) 、[`libc++`](https://github.com/llvm/llvm-project/blob/7ac7d418ac2b16fd44789dcf48e2b5d73de3e715/libcxx/include/mutex#L424-L488)的实现,并没有太多区别,更多的是一些风格上的。而且个人觉得 MSVC 的实现是最简单直观的。 ## `std:scoped_lock` 的数据成员