マルチスレッドと例外処理
C++でマルチスレッドのプログラムを書く場合、子スレッドで発生した例外を親スレッドにどう伝えるかが問題になります。C++には例外オブジェクトのディープコピーを行う統一したメカニズムはありませんから、単純に親スレッドへコピーすることはできません。
実際のところ、例外オブジェクトはstd::exceptionから派生することが多く、std::exceptionが提供するのはwhat()の返す文字列ぐらいのものです。よって、ライブラリが提供する既定の動作としては、what()メッセージを親スレッドにコピーするのが現実的です。しかし、ライブラリユーザーはより多くの情報を欲しがるかもしれませんし、もしかしたら(外的要因により)std::exceptionから派生していない例外を使うかもしれません。
このような場合、自分が良く使う手は例外の再スローを用いて例外の判定を含んだ処理までポリシークラスに行わせるというものです。
// <hamigaki/thread/exception_storage.hpp> class exception_storage { public: void reset() { what_.clear(); } void store() { try { throw; // 再スロー } catch (const std::exception& e) { try { what_ = e.what(); } catch (...) { } } catch (...) { } } const std::string& what() const { return what_; } private: std::string what_; }; template<class ExceptionStorage=exception_storage> void some_func(ExceptionStorage& storage) { try { // 何かの処理 } catch (...) { storage.store(); } }
こうしておけば、ポリシークラスを切り替えることで例外の処理方法を変更することができます。
この仕組みをcopy_managerに追加してみました。