@@ -387,23 +387,25 @@ int main(){
387
387
388
388
而我们先前一直没有写明这个参数,是因为 ` std::async ` 函数模板有两个** 重载** ,不给出执行策略就是以:` std::launch::async | std::launch::deferred ` 调用另一个重载版本(这一点中在[ 源码] ( https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L1425-L1430 ) 中很明显),此策略表示由实现选择到底是否创建线程执行异步任务。典型情况是,如果系统资源充足,并且异步任务的执行不会导致性能问题,那么系统可能会选择在新线程中执行任务。但是,如果系统资源有限,或者延迟执行可以提高性能或节省资源,那么系统可能会选择延迟执行。
389
389
390
+ > 如果你阅读 [ ` libstdc++ ` ] ( https://github.com/gcc-mirror/gcc/blob/bcb9dad/libstdc%2B%2B-v3/include/std/future#L1818-L1819 ) 的代码,会发现的确如此。
391
+ >
390
392
> 然而值得注意的是,在 MSVC STL 的实现中,` launch::async | launch::deferred ` 与 ` launch::async ` 执行策略毫无区别,[ ** 源码** ] ( https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L1400-L1410 ) 如下:
391
393
>
392
394
> ``` cpp
393
395
> template <class _Ret , class _ Fty>
394
396
> _Associated_state<typename _P_arg_type<_Ret>::type>* _Get_associated_state (launch _ Psync, _ Fty&& _ Fnarg) {
395
- > // construct associated asynchronous state object for the launch type
396
- > switch (_Psync) { // select launch type
397
- > case launch::deferred:
398
- > return new _Deferred_async_state<_Ret>(_STD forward<_Fty>(_Fnarg));
399
- > case launch::async: // TRANSITION, fixed in vMajorNext, should create a new thread here
400
- > default:
401
- > return new _Task_async_state<_Ret>(_STD forward<_Fty>(_Fnarg));
402
- > }
397
+ > // construct associated asynchronous state object for the launch type
398
+ > switch (_Psync) { // select launch type
399
+ > case launch::deferred:
400
+ > return new _Deferred_async_state<_Ret>(_STD forward<_Fty>(_Fnarg));
401
+ > case launch::async: // TRANSITION, fixed in vMajorNext, should create a new thread here
402
+ > default:
403
+ > return new _Task_async_state<_Ret>(_STD forward<_Fty>(_Fnarg));
404
+ > }
403
405
> }
404
406
> ```
405
407
>
406
- > 且 `_Task_async_state` 会通过 [`::Concurrency::create_task`](https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L663-L665) 从线程池中获取线程并执行任务返回包装对象。
408
+ > 且 `_Task_async_state` 会通过 [`::Concurrency::create_task`](https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L663-L665)[^1] 从线程池中获取线程并执行任务返回包装对象。
407
409
>
408
410
> 简而言之,使用 `std::async`,只要不是 `launch::deferred` 策略,那么 MSVC STL 实现中都是必然在线程中执行任务。因为是线程池,所以执行新任务是否创建新线程,任务执行完毕线程是否立即销毁,***不确定***。
409
411
@@ -447,6 +449,7 @@ int main(){
447
449
```
448
450
449
451
如同没有线程资源所有权的 ` std::thread ` 对象调用 ` join() ` 一样错误,这是移动语义的基本语义逻辑。
452
+ [ ^ 1 ] : 此设施来自微软[ 并行模式库] ( https://learn.microsoft.com/zh-cn/cpp/parallel/concrt/parallel-patterns-library-ppl?view=msvc-170 ) (PPL),它返回一个 task 类型,它的使用同样可参见[ 文档] ( https://learn.microsoft.com/zh-cn/cpp/parallel/concrt/task-parallelism-concurrency-runtime?view=msvc-170#task-class ) 。不过这不是我们的重点。
450
453
451
454
### ` future ` 与 ` std::packaged_task `
452
455
@@ -819,7 +822,7 @@ int main() {
819
822
}
820
823
```
821
824
822
- 这样访问的就都是 ` std::shared_future ` 的副本了,我们的 lambda 按复制捕获 std::shared_future 对象,每个线程都有一个 shared_future 的副本,这样不会有任何问题。这一点和 ` std::shared_ptr ` 类似[ ^ 1 ] 。
825
+ 这样访问的就都是 ` std::shared_future ` 的副本了,我们的 lambda 按复制捕获 std::shared_future 对象,每个线程都有一个 shared_future 的副本,这样不会有任何问题。这一点和 ` std::shared_ptr ` 类似[ ^ 2 ] 。
823
826
824
827
` std::promise ` 也同,它的 ` get_future() ` 成员函数一样可以用来构造 ` std::shared_future ` ,虽然它的返回类型是 ` std::future ` ,不过不影响,这是因为 ` std::shared_future ` 有一个 ` std::future<T>&& ` 参数的[ 构造函数] ( https://zh.cppreference.com/w/cpp/thread/shared_future/shared_future ) ,转移 ` std::future ` 的所有权。
825
828
@@ -830,7 +833,7 @@ std::shared_future<std::string>sf{ p.get_future() }; // 隐式转移所有权
830
833
831
834
就不需要再强调了。
832
835
833
- [^1]:注:多个线程能在不同的 shared_ptr 对象上调用所有成员函数(包含复制构造函数与复制赋值)而不附加同步,即使这些实例是同一对象的副本且共享所有权也是如此。若多个执行线程访问同一 shared_ptr 对象而不同步,且任一线程使用 shared_ptr 的非 const 成员函数,则将出现数据竞争;`std::atomic<shared_ptr>` 能用于避免数据竞争。[文档](https://zh.cppreference.com/w/cpp/memory/shared_ptr#:~:text=%E5%A4%9A%E4%B8%AA%E7%BA%BF%E7%A8%8B%E8%83%BD%E5%9C%A8%E4%B8%8D%E5%90%8C%E7%9A%84%20shared_ptr%20%E5%AF%B9%E8%B1%A1%E4%B8%8A%E8%B0%83%E7%94%A8%E6%89%80%E6%9C%89%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%EF%BC%88%E5%8C%85%E5%90%AB%E5%A4%8D%E5%88%B6%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E4%B8%8E%E5%A4%8D%E5%88%B6%E8%B5%8B%E5%80%BC%EF%BC%89%E8%80%8C%E4%B8%8D%E9%99%84%E5%8A%A0%E5%90%8C%E6%AD%A5%EF%BC%8C%E5%8D%B3%E4%BD%BF%E8%BF%99%E4%BA%9B%E5%AE%9E%E4%BE%8B%E6%98%AF%E5%90%8C%E4%B8%80%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%89%AF%E6%9C%AC%E4%B8%94%E5%85%B1%E4%BA%AB%E6%89%80%E6%9C%89%E6%9D%83%E4%B9%9F%E6%98%AF%E5%A6%82%E6%AD%A4%E3%80%82%E8%8B%A5%E5%A4%9A%E4%B8%AA%E6%89%A7%E8%A1%8C%E7%BA%BF%E7%A8%8B%E8%AE%BF%E9%97%AE%E5%90%8C%E4%B8%80%20shared_ptr%20%E5%AF%B9%E8%B1%A1%E8%80%8C%E4%B8%8D%E5%90%8C%E6%AD%A5%EF%BC%8C%E4%B8%94%E4%BB%BB%E4%B8%80%E7%BA%BF%E7%A8%8B%E4%BD%BF%E7%94%A8%20shared_ptr%20%E7%9A%84%E9%9D%9E%20const%20%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%EF%BC%8C%E5%88%99%E5%B0%86%E5%87%BA%E7%8E%B0%E6%95%B0%E6%8D%AE%E7%AB%9E%E4%BA%89%EF%BC%9Bstd%3A%3Aatomic%3Cshared_ptr%3E%20%E8%83%BD%E7%94%A8%E4%BA%8E%E9%81%BF%E5%85%8D%E6%95%B0%E6%8D%AE%E7%AB%9E%E4%BA%89%E3%80%82)。
836
+ [^2]:注:多个线程能在不同的 shared_ptr 对象上调用所有成员函数(包含复制构造函数与复制赋值)而不附加同步,即使这些实例是同一对象的副本且共享所有权也是如此。若多个执行线程访问同一 shared_ptr 对象而不同步,且任一线程使用 shared_ptr 的非 const 成员函数,则将出现数据竞争;`std::atomic<shared_ptr>` 能用于避免数据竞争。[文档](https://zh.cppreference.com/w/cpp/memory/shared_ptr#:~:text=%E5%A4%9A%E4%B8%AA%E7%BA%BF%E7%A8%8B%E8%83%BD%E5%9C%A8%E4%B8%8D%E5%90%8C%E7%9A%84%20shared_ptr%20%E5%AF%B9%E8%B1%A1%E4%B8%8A%E8%B0%83%E7%94%A8%E6%89%80%E6%9C%89%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%EF%BC%88%E5%8C%85%E5%90%AB%E5%A4%8D%E5%88%B6%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E4%B8%8E%E5%A4%8D%E5%88%B6%E8%B5%8B%E5%80%BC%EF%BC%89%E8%80%8C%E4%B8%8D%E9%99%84%E5%8A%A0%E5%90%8C%E6%AD%A5%EF%BC%8C%E5%8D%B3%E4%BD%BF%E8%BF%99%E4%BA%9B%E5%AE%9E%E4%BE%8B%E6%98%AF%E5%90%8C%E4%B8%80%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%89%AF%E6%9C%AC%E4%B8%94%E5%85%B1%E4%BA%AB%E6%89%80%E6%9C%89%E6%9D%83%E4%B9%9F%E6%98%AF%E5%A6%82%E6%AD%A4%E3%80%82%E8%8B%A5%E5%A4%9A%E4%B8%AA%E6%89%A7%E8%A1%8C%E7%BA%BF%E7%A8%8B%E8%AE%BF%E9%97%AE%E5%90%8C%E4%B8%80%20shared_ptr%20%E5%AF%B9%E8%B1%A1%E8%80%8C%E4%B8%8D%E5%90%8C%E6%AD%A5%EF%BC%8C%E4%B8%94%E4%BB%BB%E4%B8%80%E7%BA%BF%E7%A8%8B%E4%BD%BF%E7%94%A8%20shared_ptr%20%E7%9A%84%E9%9D%9E%20const%20%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%EF%BC%8C%E5%88%99%E5%B0%86%E5%87%BA%E7%8E%B0%E6%95%B0%E6%8D%AE%E7%AB%9E%E4%BA%89%EF%BC%9Bstd%3A%3Aatomic%3Cshared_ptr%3E%20%E8%83%BD%E7%94%A8%E4%BA%8E%E9%81%BF%E5%85%8D%E6%95%B0%E6%8D%AE%E7%AB%9E%E4%BA%89%E3%80%82)。
834
837
835
838
## 限时等待
836
839
0 commit comments