C++ OpenMP中优雅的异常处理

C++ OpenMP中优雅的异常处理,c++,exception-handling,c++11,openmp,C++,Exception Handling,C++11,Openmp,OpenMP禁止通过异常离开OpenMP块的代码。因此,我正在寻找一种从openmp块获取异常的好方法,目的是在主线程中重新刷新它,并在以后处理。到目前为止,我能想到的最好的方法是: class ThreadException { std::exception_ptr Ptr; std::mutex Lock; public: ThreadException(): Ptr(nullptr) {} ~ThreadException(){ this-&

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(); }
}
类线程异常{
标准::异常_ptrptr;
std::互斥锁;
公众:
ThreadException():Ptr(nullptr){}
~ThreadException(){this->Rethrow();}
空回缩(){
if(this->Ptr)std::rethrow_异常(this->Ptr);
}
无效CaptureException(){
std::唯一的锁防护装置(此->锁);
这->Ptr=std::current_exception();
}   
};
//...
例外情况除外;
#pragma-omp并行
{
试一试{
//一些可能会抛出代码
} 
catch(…){except.CaptureException();}
}
虽然这很好地工作,只要
ThreadException
对象被破坏,就从并行部分重新引用可能的异常,但是在每个部分周围放置
try{}catch(…){}
并手动捕获异常时,使用这种构造仍然有点笨拙


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

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

class ThreadException {

    // ...

    template <typename Function, typename... Parameters>
    void Run(Function f, Parameters... params)
    {
        try 
        {
            f(params...);
        }
        catch (...)
        {
            CaptureException();
        }
    }
 };
类线程异常{
// ...
模板
无效运行(函数f、参数…参数)
{
尝试
{
f(参数…);
}
捕获(…)
{
CaptureException();
}
}
};
然后在OpenMP构造内部调用时,使用lambda函数,如下所示:

ThreadException e;

#pragma omp parallel for
for (int i = 0; i < n; i++)
{
    e.Run([=]{
        // code that might throw
        // ...
    });
}
e.Rethrow()
threade;
#pragma-omp并行
对于(int i=0;i
当两个或多个线程抛出异常(可能是不同的异常)时,您将如何处理这种情况?@HristoIliev:忽略其中一个异常(因为我无论如何不能抛出更多的异常),而只重新抛出最后一个异常。从析构函数抛出是非法的(我使用了一个库来实现这一点,这给我带来了很多麻烦,直到我弄明白为什么我的应用程序一直在中止而没有捕获异常)。你必须调用
except.Rethrow()
在并行部分之后。如果在并行部分之后有顺序代码,而在发生异常时您不希望执行这些代码,那么这将是更好的方法。我认为使用
std::mutex
可能会导致未定义的行为。请参阅。但是,
#pragma omp critical
应该在这里工作。或者。出于某种奇怪的原因,我没有这样做考虑将一个函子传递给Exception类,因此感谢您的建议。另外,从析构函数调用Rethrow()时要小心,否则会崩溃并烧坏!