2012-10-02 11 views
13

W przypadku niektórych kodu wielowątkowego chciałbym przechwycić wszystkie wyjątki i przekazać je do pojedynczego wątku obsługi wyjątku. Oto wiadomość przechodząc ramy:Czy wyjątki można "duplikować" za pomocą wskaźników wyjątku?

#include <exception> 

struct message 
{ 
    virtual ~message() = default; 
    virtual void act() = 0; 
}; 

struct exception_message : message 
{ 
    std::exception_ptr ep; 

    virtual void act() 
    { 
     std::rethrow_exception(ep); 
    } 

    // ... 
}; 

oto przypadek użycia:

try 
{ 
    // ... 
} 
catch (...) 
{ 
    exception_message em { std::current_exception(); } 
    handler_thread.post_message(em); 
} 

Gwint obsługi przechodzi przez wszystkie jego wiadomości i wzywa act() i można go zainstalować własny blok try/catch, aby obsłużyć wszystkie opublikowane wyjątki.

Teraz zastanawiałem się, co się stanie, jeśli wyślę kopie tej wiadomości do wielu odbiorców. Ogólnie rzecz biorąc, może istnieć dowolna liczba adresatów, więc nie chcę nakładać arbitralnych ograniczeń na wiadomości o wyjątkach. exception_ptr jest udokumentowany jako inteligentny wskaźnik "współwłasności", a rethrow_exception "nie wprowadza wyścigu danych".

Moje pytanie: Czy uzasadnione jest powielanie aktywnego wyjątku przez przechowywanie go w postaci exception_ptr, kopiowanie ­ przy użyciu wskaźnika i wielokrotne wywoływanie ?

+2

wystarczy znaleźć pod adresem google: http://msdn.microsoft.com/en-us/library/dd293602.aspx "Transportowanie wyjątków między wątkami" – PiotrNycz

+0

Nigdy nie próbowałem czegoś takiego. Skopiowanie/zgłoszenie wyjątku do innego wątku i ponowne jego podniesienie wydaje się nieco dziwne, ponieważ po otrzymaniu wyjątku utracił on cały kontekst. oryginalny wątek, z wyjątkiem tego, co zawiera. Sprawdzając zasygnalizowany wyjątek w jednym wątku i być może rejestrując go lub cokolwiek innego, mogłem zrozumieć. –

+0

@PiotrNycz: Ta strona nie jest w C++. Nie ma 'std :: copy_exception' w C++, –

Odpowiedz

5

Z mojego rozumienia normy wynika, że ​​jest to uzasadnione. Należy jednak zauważyć, że ponowne zgłoszenie nie powoduje duplikowania wyjątku, a zatem sam udostępniony obiekt wyjątku jest wysyłany do wyścigów danych, jeśli zostanie zmodyfikowany i uzyska do niego dostęp z innych wątków w międzyczasie. Jeśli wyjątek jest tylko do odczytu (raz rzucony), nie powinieneś mieć problemu.

chodzi o czas przechowywania:

15,1 rzucanie wyjątek [except.throw]

pamięci dla obiektu wyjątków jest przydzielona w nieokreślony sposób, chyba że zaznaczono w 3,7 .4.1. Jeśli program obsługi kończy działanie przez ponowne rzucanie, kontrola jest przekazywana do innej procedury obsługi dla tego samego wyjątku. Obiekt wyjątku jest niszczony po tym, jak ostatni pozostały aktywny moduł obsługi dla wyjść wyjątków został użyty w inny sposób niż ponowne wysyłanie, lub ostatni obiekt typu std::exception_ptr (18.8.5), który odnosi się do obiektu wyjątku, jest zniszczony, w zależności od tego, co nastąpi później. W pierwszym przypadku zniszczenie ma miejsce, gdy przewodnik wyjdzie, natychmiast po zniszczeniu obiektu zadeklarowanego w deklaracji wyjątku w procedurze obsługi, jeśli taka istnieje. W tym ostatnim przypadku zniszczenie następuje przed powrotem destruktora z std::exception_ptr.

Odnośnie rasy danych:

18.8.5 Wyjątek propagacji [propagacji]

w celu określenia obecności danych rasy operacje na exception_ptr ma dostęp do obiektów i same modyfikuj tylko obiekty exception_ptr, a nie wyjątki, do których się odnoszą. Użycie obiektów rethrow_exception na tym samym obiekcie wyjątku nie spowoduje wyścigu danych.[Uwaga: jeśli rethrow_exception ponownie rzuci ten sam obiekt wyjątku (a nie kopię), równoczesny dostęp do tego obiektu wyjątku odrzuconego może wprowadzić wyścig danych. Zmiany w liczbie obiektów exception_ptr, które odnoszą się do określonego wyjątku, nie wprowadzają wyścigu danych . -end uwaga]

chodzi rethrow:

[[noreturn]] void rethrow_exception(exception_ptr p);

9 Wymaga: p nie będzie zerowy wskaźnik.

10 Zgłasza: obiekt wyjątku, do którego odnosi się p.

+0

Ja też to czytam, ale co to znaczy? Czy rzeczywisty, * ten sam * obiekt wyjątku jest zgłaszany wielokrotnie? Czy to w porządku? Czy to coś znaczy? –

+0

@KerrekSB: Co oznacza "rzucony"? 'throw' to po prostu goto/jump w kontekście wątku, który zdaje się respektować rozwijanie stosu. Dlatego nie stanowi problemu, aby 'rethrow' dokładnie ten sam obiekt kilka razy, sam obiekt może być postrzegany jako kierujący skokiem (w kierunku prawej klauzuli" catch "). –

+0

@KerrekSB - Właśnie przeszedłem to samo ćwiczenie i nie sądzę, że jest coś, co mówi, czy wielokrotne ponowne rzuty kopii tego samego obiektu 'exception_ptr' rzucają wyraźne kopie podstawowego wyjątku. Implikacja "if' rethrow_exception' ponownie rzuca ten sam wyjątek (zamiast kopii) ... "jest to, że albo jest dozwolone. W praktyce nie sądzę, aby miało to znaczenie; przechwytywanie wyjątku przez odniesienie i modyfikowanie jego zawartości jest po prostu dziwne i to jest jedyny sposób na zachowanie zmiennego zachowania w zależności od tego, czy wyjątek jest kopiowany. –

Powiązane problemy