11

OpenMP 禁止通过异常离开 openmp 块的代码。因此,我正在寻找一种从 openmp 块中获取异常的好方法,目的是在主线程中重新抛出异常并在稍后处理。到目前为止,我能想到的最好的方法如下:

class ThreadException {
    std::exception_ptr Ptr;
    std::mutex         Lock;
public:
    ThreadException(): Ptr(nullptr) {}
    ~ThreadException(){ this->Rethrow(); }  
    void Rethrow(){
        if(this->Ptr) std::rethrow_exception(this->Ptr);
    }
    void CaptureException() { 
        std::unique_lock<std::mutex> guard(this->Lock);
        this->Ptr = std::current_exception(); 
    }   
};
//...
ThreadException except;
#pragma omp parallel
{
    try {
      //some possibly throwing code
    } 
    catch(...) { except.CaptureException(); }
}

虽然这很好用,一旦对象被销毁,就从并行部分重新抛出可能的异常,但在每个部分周围放置 a 并且必须手动捕获异常时ThreadException,这种构造仍然有点笨拙。try {}catch(...){}

所以我的问题是:有没有人知道一种更优雅(不那么冗长)的方式来做到这一点(如果有,它是什么样子的)?

4

1 回答 1

15

您可以使用更多的 C++11 工具来稍微清理一下语法。将此可变成员函数添加到您的ThreadException类中:

class ThreadException {

    // ...

    template <typename Function, typename... Parameters>
    void Run(Function f, Parameters... params)
    {
        try 
        {
            f(params...);
        }
        catch (...)
        {
            CaptureException();
        }
    }
 };

然后在 OpenMP 构造内部调用时,使用如下 lambda 函数:

ThreadException e;

#pragma omp parallel for
for (int i = 0; i < n; i++)
{
    e.Run([=]{
        // code that might throw
        // ...
    });
}
e.Rethrow()
于 2012-12-20T18:45:08.053 回答