c++ - 在存在异常的情况下使用 for_each?std::exception_list
问题描述
cppreference 文档https://en.cppreference.com/w/cpp/algorithm/for_each 说:
- 如果作为算法的一部分调用的函数的执行抛出异常并且 ExecutionPolicy 是三个标准策略之一,则调用 std::terminate。对于任何其他 ExecutionPolicy,行为是实现定义的。
我解释这意味着我不能开箱即用地从for_each
传递的函数中抛出并期望捕获异常或与之相关的一些信息。
我期望使用异常的原因是我可以部分撤消(恢复)for_each
调用中所做的更改。(也许有更好的算法)。
然而,我偶然发现了一个历史版本,for_each
它有一个不同的、更有趣的行为:
- 如果策略是 std::parallel_vector_execution_policy,则调用 std::terminate
- 如果 policy 是 std::sequential_execution_policy 或 std::parallel_execution_policy,则算法以包含所有未捕获异常的 std::exception_list 退出。如果只有一个未捕获的异常,算法可能会重新抛出它,而不用包装在 std::exception_list 中。在遇到第一个异常后返回之前,算法将执行多少工作是未指定的。
这似乎意味着terminate
实际上有可能使用异常而不是 ing。
那么,为什么std::exception_list
会被淘汰呢?是不是太有争议、太复杂、太(内存)成本了?
即使我同意这个逻辑,我真的没有任何其他选择,因为并行for_each
返回void
(而不是 UnaryFunction 返回,这也令人惊讶)。因此,在我看来,该协议是撤消未完成指令std::exception_list
的必要组成部分。for_each
期望一些新的自定义策略是否合理,例如par_with_failed_list
将出现在允许undo
ing 的某个地方。
更多上下文:这种撤消失败循环的模式用于容器的构造。我想实现一个自定义(并行/顺序)uninitialized_value_construct_n
,当(任何未排序的)构造失败时“撤消”(销毁)初始化的对象。
EDIT1:不过,也许可以将 lambda 中的捕获变量传递给函数参数。此变量可以是共享并发数据,可以在异常发生时存储异常(作为 exception_list)。我想知道这是否已经完成。
EDIT2exception_list
:我在 HPX 中找到了一个实现,
https ://github.com/STEllAR-GROUP/hpx/blob/master/hpx/exception_list.hpp
https://github.com/STEllAR-GROUP/hpx/blob/master /src/exception_list.cpp
解决方案
std::exception_list
给并行算法的规范和实现增加了很多复杂性,而没有多少相应的收益。
作为用户,您可以在仿函数中处理这种情况:
struct exception_info{
ElementType* element;
std::exception_ptr exception;
};
std::vector<exception_info> exceptions;
std::mutex exceptions_mutex;
std::vector<ElementType> range=...;
std::for_each(std::execution::par,range.begin(),range.end(),[&](ElementType& element){
try{ do_stuff(element); }
catch(...){
std::lock_guard guard(exceptions_mutex);
exceptions.push_back({&element,std::current_exception()});
}});
该exceptions
列表现在将包含指向引发异常的元素和引发的异常的指针列表。
推荐阅读
- networking - 我的路由器 Internet IP 与我的公共 IP 不同
- rest - WSO2 数据服务中的休息资源错误,过程没有参数
- c# - 字节失败的自定义 DebuggerDisplayAttribute 为 0
- node.js - npm audit replace nsp check 返回 E400 错误请求
- android - 如何使用 Rx Java 实现此要求
- css - 奇怪的 CSS 图像悬停
- c# - 使用 Web API 中的令牌进行 Azure AD 和基于组的授权
- loops - assoc 数组中的 Twig 循环
- ios - iOS Firebase Crashlytics:内存不足 (OOM) 报告
- batch-file - 在批处理文件的路径中使用多个通配符