@@ -241,7 +241,7 @@ _NODISCARD_ASYNC future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>>
241
241
| - _Future_retrieved | | _State_manager<_Ty> |
242
242
+---------------------+ |----------------------|
243
243
| - _Assoc_state | -----> +-------------------------+
244
- | - _Get_only_once | | _Associated_state<_Ty> |
244
+ | - _Get_only_once | | _Associated_state<_Ty>* |
245
245
+----------------------+ +-------------------------+
246
246
```
247
247
@@ -408,3 +408,187 @@ _NODISCARD_ASYNC future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>>
408
408
```
409
409
410
410
然后也就和上面说的没什么区别了 。
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