@@ -255,7 +255,7 @@ _NODISCARD_ASYNC future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>>
255
255
256
256
很明显,这是一个函数调用,将我们 ` std::async ` 的参数全部转发给它,它是重要而直观的。
257
257
258
- ` _Get_associated_state ` 函数根据启动模式(` launch ` )来决定创建的异步任务状态对象类型:
258
+ [ ` _Get_associated_state ` ] ( https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L1400-L1410 ) 函数根据启动模式(` launch ` )来决定创建的异步任务状态对象类型:
259
259
260
260
``` cpp
261
261
template <class _Ret , class _ Fty>
@@ -277,14 +277,14 @@ _NODISCARD_ASYNC future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>>
277
277
278
278
---
279
279
280
- **`_Task_async_state` 类型**
280
+ **[ `_Task_async_state`](https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L654-L686) 类型**
281
281
282
282
```cpp
283
283
template <class _Rx>
284
284
class _Task_async_state : public _Packaged_state<_Rx()>
285
285
```
286
286
287
- ` _Task_async_state ` 是 ` _Packaged_state ` 的派生类 ,用于异步执行任务。它的构造函数接受一个函数对象,并将其传递给基类 ` _Packaged_state ` 的构造函数。
287
+ ` _Task_async_state ` 继承自 [ ` _Packaged_state ` ] ( https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L462-L597 ) ,用于异步执行任务。它的构造函数接受一个函数对象,并将其传递给基类 ` _Packaged_state ` 的构造函数。
288
288
289
289
` _Packaged_state ` 类型只有一个数据成员 ` std::function ` 类型的对象 ` _Fn ` ,它表示需要执行的异步任务,而它又继承自 _ Associated_state。
290
290
@@ -294,6 +294,25 @@ _NODISCARD_ASYNC future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>>
294
294
: public _ Associated_state<_ Ret>
295
295
```
296
296
297
+ ```mermaid
298
+ classDiagram
299
+ class _Associated_state {
300
+ ...
301
+ }
302
+
303
+ class _Packaged_state {
304
+ -std::function _Fn
305
+ }
306
+
307
+ class _Task_async_state {
308
+ -::Concurrency::task<void> _Task
309
+ }
310
+
311
+ _Associated_state <|-- _Packaged_state : 继承
312
+ _Packaged_state <|-- _Task_async_state : 继承
313
+
314
+ ```
315
+
297
316
我们直接看 ` _Task_async_state ` 类型的构造函数实现即可:
298
317
299
318
``` cpp
@@ -316,18 +335,53 @@ _NODISCARD_ASYNC future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>>
316
335
317
336
这里其实使用到了微软自己实现的 [ 并行模式库] ( https://learn.microsoft.com/zh-cn/cpp/parallel/concrt/parallel-patterns-library-ppl?view=msvc-170 ) (PPL),简而言之 ` async ` 策略并不是单纯的创建线程让任务执行,而是使用了微软的 ` ::Concurrency::create_task ` ,它从** 线程池** 中获取线程并执行任务返回包装对象。
318
337
319
- ` this->_Call_immediate(); ` 是调用的父类 ` _Packaged_state ` 的成员函数:
338
+ ` this->_Call_immediate(); ` 是调用 ` _Task_async_state ` 的父类 ` _Packaged_state ` 的成员函数 ` _Call_immediate ` 。
339
+
340
+ ** ` _Packaged_state ` 有三个偏特化** ,` _Call_immediate ` 自然也拥有三个不同版本,用来应对我们传入的函数对象** 返回类型** 的三种情况:
341
+
342
+ - 返回普通类型 [`_Packaged_state<_Ret(_ArgTypes...)>`](https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L554)
343
+
344
+ ```cpp
345
+ void _Call_immediate(_ArgTypes... _Args) {
346
+ _TRY_BEGIN
347
+ // 调用函数对象并捕获异常 传递返回值
348
+ this->_Set_value(_Fn(_STD forward<_ArgTypes>(_Args)...), false);
349
+ _CATCH_ALL
350
+ // 函数对象抛出异常就记录
351
+ this->_Set_exception(_STD current_exception(), false);
352
+ _CATCH_END
353
+ }
354
+ ```
355
+
356
+ - 返回引用类型 [`_Packaged_state<_Ret&(_ArgTypes...)>`](https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L510)
357
+
358
+ ```cpp
359
+ void _Call_immediate(_ArgTypes... _Args) {
360
+ _TRY_BEGIN
361
+ // 调用函数对象并捕获异常 传递返回值的地址
362
+ this->_Set_value(_STD addressof(_Fn(_STD forward<_ArgTypes>(_Args)...)), false);
363
+ _CATCH_ALL
364
+ // 函数对象抛出异常就记录
365
+ this->_Set_exception(_STD current_exception(), false);
366
+ _CATCH_END
367
+ }
368
+ ```
369
+
370
+ - 返回 void 类型 [ ` _Packaged_state<void(_ArgTypes...)> ` ] ( https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L554 )
320
371
321
372
``` cpp
322
373
void _Call_immediate (_ ArgTypes... _ Args) { // call function object
323
374
_ TRY_BEGIN
324
- // call function object and catch exceptions
325
- this->_ Set_value(_ Fn(_ STD forward<_ ArgTypes>(_ Args)...), false);
375
+ // 调用函数对象并捕获异常 因为返回 void 不获取返回值 而是直接 _ Set_value 传递一个 1
376
+ _ Fn(_ STD forward<_ ArgTypes>(_ Args)...);
377
+ this->_ Set_value(1, false);
326
378
_ CATCH_ALL
327
- // function object threw exception; record result
379
+ // 函数对象抛出异常就记录
328
380
this->_ Set_exception(_ STD current_exception(), false);
329
381
_ CATCH_END
330
382
}
331
383
```
332
384
333
- 它则调用了 `_Associated_state` 的成员函数(`_Set_value`、`_set_exception`),传递的可调用对象执行结果,以及可能的异常,将结果或异常存储在 `_Associated_state` 中。
385
+ 说白了,无非是把返回引用类型的可调用对象返回的引用获取地址传递给 `_Set_value`,把返回 void 类型的可调用对象传递一个 1 表示正确执行的状态给 `_Set_value`。
386
+
387
+ `_Call_immediate` 则又调用了父类 `_Associated_state` 的成员函数(`_Set_value`、`_set_exception`),传递的可调用对象执行结果,以及可能的异常,将结果或异常存储在 `_Associated_state` 中。
0 commit comments