Skip to content

Commit 8714ced

Browse files
committed
更新源码解析的部分内容 Mq-b#12
1 parent a8bd60e commit 8714ced

File tree

1 file changed

+61
-2
lines changed

1 file changed

+61
-2
lines changed

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

+61-2
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,9 @@ _NODISCARD_ASYNC future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>>
253253

254254
`_Get_associated_state<_Ret>(_Policy, _Fake_no_copy_callable_adapter<_Fty, _ArgTypes...>(_STD forward<_Fty>(_Fnarg), _STD forward<_ArgTypes>(_Args)...))`
255255

256-
很明显,这是一个函数调用,将我们 `std::async` 的参数全部转发给它,它是重要而直观的,代码如下:
256+
很明显,这是一个函数调用,将我们 `std::async` 的参数全部转发给它,它是重要而直观的。
257+
258+
`_Get_associated_state` 函数根据启动模式(`launch`)来决定创建的异步任务状态对象类型:
257259

258260
```cpp
259261
template <class _Ret, class _Fty>
@@ -271,4 +273,61 @@ _NODISCARD_ASYNC future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>>
271273
272274
`_Get_associated_state` 函数返回一个 `_Associated_state` 指针,该指针指向一个新的 `_Deferred_async_state` 或 `_Task_async_state` 对象。这两个类分别对应于异步任务的两种不同执行策略:**延迟执行**和**异步执行**。
273275
274-
> 这也就是证明了在 MSVC STL 的实现中,`launch::async | launch::deferred` 与 `launch::async` 执行策略**毫无区别**。这段代码的 `switch` 语句有两个 `case` 和一个 `default`,如你所见,`case launch::async` 是为空的,除了 `launch::deferred` 最终都会进入 `default`,即都执行 `launch::async` 策略。
276+
> 这段代码也很好的说明在 MSVC STL 中,`launch::async | launch::deferred` 和 `launch::async` 的行为是相同的,即都是异步执行。
277+
278+
---
279+
280+
**`_Task_async_state` 类型**
281+
282+
```cpp
283+
template <class _Rx>
284+
class _Task_async_state : public _Packaged_state<_Rx()>
285+
```
286+
287+
`_Task_async_state``_Packaged_state` 的派生类,用于异步执行任务。它的构造函数接受一个函数对象,并将其传递给基类 `_Packaged_state` 的构造函数。
288+
289+
`_Packaged_state` 类型只有一个数据成员 `std::function` 类型的对象 `_Fn`,它表示需要执行的异步任务,而它又继承自 _Associated_state。
290+
291+
```cpp
292+
template <class _Ret, class... _ArgTypes>
293+
class _Packaged_state<_Ret(_ArgTypes...)>
294+
: public _Associated_state<_Ret>
295+
```
296+
297+
我们直接看 `_Task_async_state` 类型的构造函数实现即可:
298+
299+
```cpp
300+
template <class _Fty2>
301+
_Task_async_state(_Fty2&& _Fnarg) : _Mybase(_STD forward<_Fty2>(_Fnarg)) {
302+
_Task = ::Concurrency::create_task([this]() { // do it now
303+
this->_Call_immediate();
304+
});
305+
306+
this->_Running = true;
307+
}
308+
```
309+
310+
它的数据成员:
311+
312+
```cpp
313+
private:
314+
::Concurrency::task<void> _Task;
315+
```
316+
317+
这里其实使用到了微软自己实现的 [并行模式库](https://learn.microsoft.com/zh-cn/cpp/parallel/concrt/parallel-patterns-library-ppl?view=msvc-170)(PPL),简而言之 `async` 策略并不是单纯的创建线程让任务执行,而是使用了微软的 `::Concurrency::create_task` ,它从**线程池**中获取线程并执行任务返回包装对象。
318+
319+
`this->_Call_immediate();` 是调用的父类 `_Packaged_state` 的成员函数:
320+
321+
```cpp
322+
void _Call_immediate(_ArgTypes... _Args) { // call function object
323+
_TRY_BEGIN
324+
// call function object and catch exceptions
325+
this->_Set_value(_Fn(_STD forward<_ArgTypes>(_Args)...), false);
326+
_CATCH_ALL
327+
// function object threw exception; record result
328+
this->_Set_exception(_STD current_exception(), false);
329+
_CATCH_END
330+
}
331+
```
332+
333+
它则调用了 `_Associated_state` 的成员函数(`_Set_value`、`_set_exception`),传递的可调用对象执行结果,以及可能的异常,将结果或异常存储在 `_Associated_state` 中。

0 commit comments

Comments
 (0)