C++ 之 std::exception_ptr

火山方舟向量数据库大模型
  
/*  
Warning: parallel_for does NOT copy thread local  
states from the current thread to the worker threads.  
This means for example that Tensor operations CANNOT be used in the  
body of your function, **only data pointers**.  
*/  
template <class F>  
inline void parallel_for(  
    const int64_t begin,  
    const int64_t end,  
    const int64_t grain_size,  
    const F& f);  

从 parallel_for 的注释中知道在并行区域中只能使用data pointer,其异常处理通过 std::exception_ptr 实现。

  
# https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/ParallelOpenMP.h  
  
template <typename F>  
inline void invoke\_parallel(  
    int64\_t begin,  
    int64\_t end,  
    int64\_t grain\_size,  
    const F& f) {  
  ...  
  std::exception_ptr eptr;  
  
#pragma omp parallel  
  {  
    ...  
    if (begin_tid < end) {  
      try {  
        internal::ThreadIdGuard tid\_guard(tid);  
        f(begin_tid, std::min(end, chunk_size + begin_tid));  
      } catch (...) {  
        if (!err_flag.test_and_set()) {  
          eptr = std::current_exception();  
        }  
      }  
    }  
  }  
  if (eptr) {  
    std::rethrow_exception(eptr);  
  }  
}  

std::exception_ptr

std::exception_ptr是一个可空的 pointer-like 类型,它管理一个由std::current_exception捕获的异常对象。std::exception_ptr的实例可以传递给另一个函数,可能是在另一个线程上,该异常可以被重新抛出并使用catch子句处理。

默认构造的std::exception_ptr是空指针;它不指向异常对象。

std::exception_ptr的两个实例只有当它们都为空或都指向同一个异常对象时才相等。

std::exception_ptr不能隐式转换为任何算术、枚举或指针类型。它可根据上下文条件下转换为bool,如果为null,则计算为false,否则为true

std::exception_ptr引用的异常对象只要至少有一个std::exception_ptr引用它,它就仍然有效。这是对通常的异常对象生命周期规则的补充)

std::exception_ptr满足NullablePointer的要求。

std::make_exception_ptr

  
template< class E >  
std::exception\_ptr make\_exception\_ptr( E e ) noexcept;  

创建一个std::exception_ptr,它持有e副本的引用。这就像执行以下代码一样:

  
try {  
    throw e;  
} catch(...) {  
    return std::current_exception();  
}  

std::current_exception

  
std::exception\_ptr current\_exception() noexcept;  

如果在异常处理期间调用(通常是在catch子句中),则捕获当前异常对象并创建一个std::exception_ptr,该std::exception_ptr包含该异常对象的副本或引用(取决于实现)。被引用的对象至少只要有一个引用它的exception_ptr对象,它就仍然有效。

如果该函数的实现需要调用new并且调用失败,则返回的指针将保存对std::bad_alloc实例的引用。

如果此函数的实现需要复制捕获的异常对象,并且其复制构造函数抛出异常,则返回的指针将持有对所抛出异常的引用。如果抛出异常对象的复制构造函数也抛出异常,则返回的指针可以持有对std::bad_exception实例的引用,以中断循环。

如果在不处理异常的情况下调用函数,则返回一个空的std::exception_ptr

std::rethrow_exception

  
[[noreturn]] void rethrow\_exception( std::exception\_ptr p );  

抛出异常指针p引用的先前捕获的异常对象,或该对象的副本。

如果p为空,则行为未定义。

Example

  
#include <iostream>  
#include <string>  
#include <exception>  
#include <stdexcept>  
   
void handle\_eptr(std::exception\_ptr eptr) // passing by value is ok  
{  
    try {  
        if (eptr) {  
            std::rethrow_exception(eptr);  
        }  
    } catch(const std::exception& e) {  
        std::cout << "Caught exception \"" << e.what() << "\"\n";  
    }  
}  
   
int main()  
{  
    std::exception_ptr eptr;  
    try {  
        std::string().at(1); // this generates an std::out\_of\_range  
    } catch(...) {  
        eptr = std::current_exception(); // capture  
    }  
    handle_eptr(eptr);  
} // destructor for std::out\_of\_range called here, when the eptr is destructed  

参考文献

picture.image

0
0
0
0
关于作者

文章

0

获赞

0

收藏

0

相关资源
vivo 容器化平台架构与核心能力建设实践
为了实现规模化降本提效的目标,vivo 确定了基于云原生理念构建容器化生态的目标。在容器化生态发展过程中,平台架构不断演进,并针对业务的痛点和诉求,持续完善容器化能力矩阵。本次演讲将会介绍 vivo 容器化平台及主要子系统的架构设计,并分享重点建设的容器化核心能力。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论