Skip to content

Commit 4f43473

Browse files
committed
更新不重要的文件。修改 std::thread 源码解析中的措辞。
1 parent f631df4 commit 4f43473

9 files changed

+231
-2
lines changed
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
#include <iostream>
2+
#include <thread>
3+
#include <chrono>
24

3-
int main(){
5+
void hello(){
46
std::cout << "Hello World" << std::endl;
7+
// std::this_thread::sleep_for(std::chrono::seconds(5));
8+
}
9+
10+
int main(){
11+
std::thread t; // 默认构造?构造不关联线程的 thread 对象
12+
std::cout <<std::boolalpha<< t.joinable() << '\n'; // false
513
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include <iostream>
2+
#include <thread>
3+
#include <algorithm>
4+
#include <numeric>
5+
#include <iterator>
6+
#include <vector>
7+
8+
template<typename ForwardIt>
9+
auto sum(ForwardIt first, ForwardIt last) {
10+
using value_type = std::iter_value_t<ForwardIt>;
11+
std::size_t num_threads = std::thread::hardware_concurrency();
12+
std::ptrdiff_t distance = std::distance(first, last);
13+
14+
if (distance > 1024000) {
15+
// 计算每个线程处理的元素数量
16+
std::size_t chunk_size = distance / num_threads;
17+
std::size_t remainder = distance % num_threads;
18+
19+
// 存储每个线程的结果
20+
std::vector<value_type> results{ num_threads };
21+
22+
// 存储关联线程的线程对象
23+
std::vector<std::thread> threads;
24+
25+
// 创建并启动线程
26+
auto start = first;
27+
for (std::size_t i = 0; i < num_threads; ++i) {
28+
auto end = std::next(start, chunk_size + (i < remainder ? 1 : 0));
29+
threads.emplace_back([start, end, &results, i] {
30+
results[i] = std::accumulate(start, end, value_type{});
31+
});
32+
start = end; // 开始迭代器不断向前
33+
}
34+
35+
// 等待所有线程执行完毕
36+
for (auto& thread : threads)
37+
thread.join();
38+
39+
// 汇总线程的计算结果
40+
value_type total_sum = std::accumulate(results.begin(), results.end(), value_type{});
41+
return total_sum;
42+
}
43+
44+
value_type total_sum = std::accumulate(first, last, value_type{});
45+
return total_sum;
46+
}
47+
48+
int main() {
49+
std::vector<std::string> vecs{ "1","2","3","4" };
50+
auto result = sum(vecs.begin(), vecs.end());
51+
std::cout << result << '\n';
52+
53+
vecs.clear();
54+
for (std::size_t i = 0; i <= 1024001u; ++i) {
55+
vecs.push_back(std::to_string(i));
56+
}
57+
result = sum(vecs.begin(), vecs.end());
58+
std::cout << result << '\n';
59+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <iostream>
2+
#include <thread>
3+
4+
struct func {
5+
int& m_i;
6+
func(int& i) :m_i{ i } {}
7+
void operator()(int n)const {
8+
for (int i = 0; i <= n; ++i) {
9+
m_i += i; // 可能悬空引用
10+
}
11+
}
12+
};
13+
14+
void f2() { throw std::runtime_error("test f2()"); }
15+
16+
void f() {
17+
int n = 0;
18+
std::thread t{ func{n},10 };
19+
try {
20+
// todo.. 一些当前线程可能抛出异常的代码
21+
f2();
22+
t.join();
23+
}
24+
catch (...) {
25+
t.join(); // 1
26+
// 如果此处不抛出 会掩盖错误 我们根本没有处理 没有解决
27+
}
28+
}
29+
30+
int main() {
31+
f();
32+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include <iostream>
2+
#include <thread>
3+
#include <exception>
4+
5+
struct func {
6+
int& m_i;
7+
func(int& i) :m_i{ i } {}
8+
void operator()(int n)const {
9+
for (int i = 0; i <= n; ++i) {
10+
m_i += i; // 可能悬空引用
11+
}
12+
}
13+
};
14+
15+
void f2(){
16+
// todo..
17+
throw std::runtime_error("f2 error");
18+
}
19+
20+
class thread_guard{
21+
public:
22+
explicit thread_guard(std::thread& t) :thread_{ t }
23+
{}
24+
~thread_guard(){
25+
std::puts("析构");
26+
if(thread_.joinable()){ // 如果当前有活跃线程 则进行 join
27+
thread_.join();
28+
}
29+
}
30+
thread_guard& operator=(const thread_guard&) = delete;
31+
thread_guard(const thread_guard&) = delete;
32+
33+
std::thread& thread_;
34+
};
35+
36+
void f() {
37+
int n = 0;
38+
std::thread t{ func{n},10 };
39+
thread_guard g(t);
40+
f2(); // 可能抛出异常
41+
}
42+
43+
int main(){
44+
// 栈回溯
45+
try{
46+
f();
47+
}catch (...){}
48+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <iostream>
2+
#include <thread>
3+
#include <functional>
4+
5+
void f(const std::string&);
6+
7+
void test() {
8+
char buffer[1024]{};
9+
//todo.. code
10+
std::thread t{ f, std::string(buffer) }; // std::string(buffer) 构造对象,由 std::string 对象自行管理
11+
t.detach();
12+
}
13+
14+
int main(){
15+
// A 的引用只能引用 A 类型,或者以任何形式 转换到 A
16+
double a = 1;
17+
const int& p = a; // a 隐式转换到了 int 类型,这个转换是纯右值表达式
18+
// 因为 const T& 可以接右值表达式,所以才能通过编译
19+
const std::string& s = "123"; // "123" 构造了 std::string 对象
20+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <iostream>
2+
#include <thread>
3+
#include <chrono>
4+
using namespace std::chrono_literals;
5+
6+
int main() {
7+
// 获取当前时间点
8+
auto now = std::chrono::system_clock::now();
9+
10+
// 设置要等待的时间点为当前时间点之后的5秒
11+
auto wakeup_time = now + 5s;
12+
13+
// 输出当前时间
14+
auto now_time = std::chrono::system_clock::to_time_t(now);
15+
std::cout << "Current time:\t\t" << std::put_time(std::localtime(&now_time), "%H:%M:%S") << std::endl;
16+
17+
// 输出等待的时间点
18+
auto wakeup_time_time = std::chrono::system_clock::to_time_t(wakeup_time);
19+
std::cout << "Waiting until:\t\t" << std::put_time(std::localtime(&wakeup_time_time), "%H:%M:%S") << std::endl;
20+
21+
// 等待到指定的时间点
22+
std::this_thread::sleep_until(wakeup_time);
23+
24+
// 输出等待结束后的时间
25+
now = std::chrono::system_clock::now();
26+
now_time = std::chrono::system_clock::to_time_t(now);
27+
std::cout << "Time after waiting:\t" << std::put_time(std::localtime(&now_time), "%H:%M:%S") << std::endl;
28+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <iostream>
2+
#include <thread>
3+
4+
// https://github.com/Mq-b/Loser-HomeWork/discussions/206
5+
6+
// 反直觉
7+
// 形参、实参
8+
// 函数调用传参,实际上是初始化了(构造)形参的对象
9+
10+
void f(std::thread t) {
11+
t.join();
12+
}
13+
14+
int main() {
15+
std::thread t{ [] {} };
16+
f(std::move(t));
17+
f(std::thread{ [] {} });
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <iostream>
2+
#include <thread>
3+
#include <type_traits>
4+
5+
struct X {
6+
X(X&& x)noexcept {}
7+
template <class Fn, class... Args, std::enable_if_t<!std::is_same_v<std::remove_cvref_t<Fn>, X>, int> = 0>
8+
X(Fn&& f, Args&&...args) {}
9+
X(const X&) = delete;
10+
};
11+
12+
int main(){
13+
std::thread
14+
X x{ [] {} };
15+
X x2{ x }; // 选择到了有参构造函数,不导致编译错误
16+
}

md/详细分析/01thread的构造与源码解析.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ void _Start(_Fn&& _Fx, _Args&&... _Ax) {
131131

132132
4. `constexpr auto _Invoker_proc = _Get_invoke<_Tuple>(make_index_sequence<1 + sizeof...(_Args)>{})`
133133

134-
- 调用 [`_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)用来实际执行线程。这两个函数都非常的简单,我们来看看:
134+
- 调用 [`_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)它是线程实际执行的函数。这两个函数都非常的简单,我们来看看:
135135

136136
```cpp
137137
template <class _Tuple, size_t... _Indices>

0 commit comments

Comments
 (0)