2012-08-06 35 views
6

OpenMP, açık bloku istisna olmak üzere terk eden kodu yasaklar. Bu yüzden bir openmp bloğundan istisnaları ana iş parçacığında yeniden düzenlemek ve daha sonra ele almak için iyi bir yol arıyorum.OpenMP'de zarif istisna işlemleri

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(); } 
} 

bu kısa sürede ThreadException nesne yok edilir gibi paralel bölümünden olası istisnalar yeniden atma, güzel çalışıyor, bu yapı hala geçerli: Şimdiye kadar ile gelip başardık iyi şudur Her bölümün etrafında bir try {}catch(...){} koyarak ve istisnayı el ile ele geçirmek zorunda kalmamak için biraz kullanışlıdır.

Dolayısıyla sorum şu: Bunu yapmak için daha zarif (daha az ayrıntılı) bir yol bilen var mı (eğer öyleyse, neye benziyor)?

+0

iki veya daha fazla iplik istisnalar atmak nasıl olaya el olur (muhtemelen farklı olanlar)? –

+0

@HristoIliev: Onlardan birini görmezden geldiğim için (o zamandan beri bir istisna daha atamam) ve sadece sonuncuyu tekrar canlandırmak. – Grizzly

+0

Bir yıkıcıdan atmak yasadışıdır (bunu yapan bir kütüphane kullandım ve başvurumun neden istisnai duruma düşmeden niçin iptal edilmediğini anlayana kadar bana bir sürü baş ağrısı getirdi). Paralel bölümden sonra 'except.Remberrow()' 'ı çağırmalısınız. Bir istisna meydana geldiğinde, yürütmek istemediğiniz paralel bölümden sonra sıralı kod varsa, bu herhangi bir şekilde daha iyi olacaktır. –

cevap

8

Sözdizimini biraz temizlemek için birkaç C++ 11 aracı kullanabilirsiniz. senin ThreadException sınıfına bu variadic üye işlevini ekleyin: Sonra

class ThreadException { 

    // ... 

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

bir OpenMP yapı içine çağrılırken şöyle bir lambda fonksiyonu kullanmak:

ThreadException e; 

#pragma omp parallel for 
for (int i = 0; i < n; i++) 
{ 
    e.Run([=]{ 
     // code that might throw 
     // ... 
    }); 
} 
e.Rethrow() 
+0

Bazı garip nedenlerden dolayı, Exception sınıfına bir functor geçirmeyi düşünmemiştim, bu yüzden öneri için teşekkürler. – Grizzly

+1

Ayrıca, yıkıcıdan Rethrow() çağrısına dikkat edin; –