Skip to content

Commit e191580

Browse files
committed
暂缓协程部分,更新源码解析内容 Mq-b#12
1 parent f05fa42 commit e191580

File tree

2 files changed

+188
-2
lines changed

2 files changed

+188
-2
lines changed

md/06协程.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
既然是“**现代**” C++ 并发编程教程,怎么能不聊协程呢?
44

5-
C++20 引入了协程语法,新增了三个用作协程的关键字:`co_await``co_yield``co_return`。但并未给出标准**协程库**协程库在 C++23 被引入。
5+
C++20 引入了协程语法,新增了三个用作协程的关键字:`co_await``co_yield``co_return`。但并未给出标准**协程库**协程库在 C++23 被引入。
66

77
希望您拥有 `gcc14``clang18`,最新的 MSVC。
8+
9+
> C++ 20 协程的使用尚不成熟,等待后续更新讲解.....

md/详细分析/03async与future源码解析.md

Lines changed: 185 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ _NODISCARD_ASYNC future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>>
241241
| - _Future_retrieved | | _State_manager<_Ty> |
242242
+---------------------+ |----------------------|
243243
| - _Assoc_state | -----> +-------------------------+
244-
| - _Get_only_once | | _Associated_state<_Ty> |
244+
| - _Get_only_once | | _Associated_state<_Ty>* |
245245
+----------------------+ +-------------------------+
246246
```
247247

@@ -408,3 +408,187 @@ _NODISCARD_ASYNC future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>>
408408
```
409409

410410
然后也就和上面说的没什么区别了 。
411+
412+
7. 返回 `std::future`
413+
414+
`return future<_Ret>(_From_raw_state_tag{}, _Pr._Get_state_for_future());`
415+
416+
它选择到了 `std::future` 的构造函数是:
417+
418+
```cpp
419+
future(_From_raw_state_tag, const _Mybase& _State) noexcept : _Mybase(_State, true) {}
420+
```
421+
422+
> ```cpp
423+
> using _Mybase = _State_manager<_Ty*>;
424+
> ```
425+
426+
`_From_raw_state_tag` 是一个空类,并没有什么特殊作用,只是为了区分重载。
427+
428+
`_Get_state_for_future` 代码如下:
429+
430+
```cpp
431+
_State_manager<_Ty>& _Get_state_for_future() {
432+
if (!_State.valid()) {
433+
_Throw_future_error2(future_errc::no_state);
434+
}
435+
436+
if (_Future_retrieved) {
437+
_Throw_future_error2(future_errc::future_already_retrieved);
438+
}
439+
440+
_Future_retrieved = true;
441+
return _State;
442+
}
443+
```
444+
445+
检查状态,修改状态,返回底层 `_State` ,完成转移状态。
446+
447+
总而言之这行代码通过调用 `std::future` 的特定构造函数,将 `_Promise` 对象中的 `_State_manager` 状态转移到 `std::future` 对象中,从而创建并返回一个 `std::future` 对象。这使得 `std::future` 可以访问并管理异步任务的状态,包括获取任务的结果或异常,并等待任务的完成。
448+
449+
## `std::future`
450+
451+
先前的 `std::async` 的内容非常之多,希望各位开发者不要搞晕了,其实重中之重主要是那几个类,关系图如下:
452+
453+
```plaintext
454+
+---------------------+
455+
| _Promise<_Ty> |
456+
|---------------------|
457+
| - _State | -----> +---------------------+
458+
| - _Future_retrieved | | _State_manager<_Ty> |
459+
+---------------------+ |----------------------|
460+
| - _Assoc_state | -----> +-------------------------+
461+
| - _Get_only_once | | _Associated_state<_Ty>* |
462+
+----------------------+ +-------------------------+
463+
```
464+
465+
> `_Promise`_`State_manager``_Associated_state` 之间的**包含关系示意图**
466+
467+
```mermaid
468+
classDiagram
469+
class _Associated_state {
470+
...
471+
}
472+
473+
class _Packaged_state {
474+
-std::function _Fn
475+
}
476+
477+
class _Task_async_state {
478+
-::Concurrency::task<void> _Task
479+
}
480+
481+
class _Deferred_async_state {
482+
}
483+
484+
_Associated_state <|-- _Packaged_state : 继承
485+
_Packaged_state <|-- _Task_async_state : 继承
486+
_Packaged_state <|-- _Deferred_async_state : 继承
487+
488+
```
489+
490+
> `_Asscociated_state``_Packaged_state``_Task_async_state``_Deferred_async_state` **继承关系示意图**
491+
492+
这其中的 `_Associated_state``_State_manager` 类型是我们的核心,它在后续 `std::future` 乃至其它并发设施都有众多使用。
493+
494+
---
495+
496+
介绍 `std::future` 的源码我认为无需过多篇幅或者示例,引入过多的源码实现等等从头讲解,只会让各位开发者感觉复杂难。
497+
498+
我们直接从它的最重要、常见的 `get()``wait()` 成员函数开始即可。
499+
500+
```cpp
501+
std::future<int> future = std::async([] { return 0; });
502+
future.get();
503+
```
504+
505+
我们先前已经详细介绍过了 `std::async` 返回 `std::future` 的步骤。以上这段代码,唯一的问题是:*`future.get()` 做了什么?*
506+
507+
```cpp
508+
_EXPORT_STD template <class _Ty>
509+
class future : public _State_manager<_Ty> {
510+
// class that defines a non-copyable asynchronous return object that holds a value
511+
private:
512+
using _Mybase = _State_manager<_Ty>;
513+
514+
public:
515+
static_assert(!is_array_v<_Ty> && is_object_v<_Ty> && is_destructible_v<_Ty>,
516+
"T in future<T> must meet the Cpp17Destructible requirements (N4950 [futures.unique.future]/4).");
517+
518+
future() = default;
519+
520+
future(future&& _Other) noexcept : _Mybase(_STD move(_Other), true) {}
521+
522+
future& operator=(future&&) = default;
523+
524+
future(_From_raw_state_tag, const _Mybase& _State) noexcept : _Mybase(_State, true) {}
525+
526+
_Ty get() {
527+
// block until ready then return the stored result or throw the stored exception
528+
future _Local{_STD move(*this)};
529+
return _STD move(_Local._Get_value());
530+
}
531+
532+
_NODISCARD shared_future<_Ty> share() noexcept {
533+
return shared_future<_Ty>(_STD move(*this));
534+
}
535+
536+
future(const future&) = delete;
537+
future& operator=(const future&) = delete;
538+
};
539+
```
540+
541+
> `std::future` 其实还有两种特化,不过整体大差不差。
542+
>
543+
> ```cpp
544+
> template <class _Ty>
545+
> class future<_Ty&> : public _State_manager<_Ty*>
546+
> ```
547+
>
548+
> ```cpp
549+
> template <>
550+
> class future<void> : public _State_manager<int>
551+
> ```
552+
>
553+
> 也就是对返回类型为引用和 void 的情况了。其实先前已经聊过很多次了,无非就是内部的返回引用实际按指针操作,返回 void,那么也得给个 1。参见前面的 `_Call_immediate` 实现。
554+
555+
可以看到 `std::future` 整体代码实现很少,很简单,那是因为其实现细节都在其父类 `_State_manager` 。然而 `_State_manager` 又保有一个 `_Associated_state<_Ty>*` 类型的成员。而 **`_Associated_state` 又是一切的核心**,之前已经详细描述过了。
556+
557+
阅读 `std::future` 的源码你可能注意到了一个问题:*没有 `wait()`*成员函数?*
558+
559+
它的定义来自于父类 `_State_manager` :
560+
561+
```cpp
562+
void wait() const { // wait for signal
563+
if (!valid()) {
564+
_Throw_future_error2(future_errc::no_state);
565+
}
566+
567+
_Assoc_state->_Wait();
568+
}
569+
```
570+
571+
然而这还不够,实际上还需要调用了 `_Associated_state``wait()` 成员函数:
572+
573+
```cpp
574+
virtual void _Wait() { // wait for signal
575+
unique_lock<mutex> _Lock(_Mtx);
576+
_Maybe_run_deferred_function(_Lock);
577+
while (!_Ready) {
578+
_Cond.wait(_Lock);
579+
}
580+
}
581+
```
582+
583+
先使用锁进行保护,然后调用函数,再循环等待任务执行完毕。关键实际上在于 `_Maybe_run_deferred_function`
584+
585+
```cpp
586+
void _Maybe_run_deferred_function(unique_lock<mutex>& _Lock) { // run a deferred function if not already done
587+
if (!_Running) { // run the function
588+
_Running = true;
589+
_Run_deferred_function(_Lock);
590+
}
591+
}
592+
```
593+
594+
`_Run_deferred_function` 相信你不会陌生,在讲述 `std::async` 源码中其实已经提到了。

0 commit comments

Comments
 (0)