![]() |
|
|||
File indexing completed on 2025-09-14 08:50:59
0001 //------------------------------- -*- C++ -*- -------------------------------// 0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details 0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 0004 //---------------------------------------------------------------------------// 0005 //! \file corecel/sys/MultiExceptionHandler.hh 0006 //---------------------------------------------------------------------------// 0007 #pragma once 0008 0009 #include <exception> 0010 #include <utility> 0011 #include <vector> 0012 0013 #include "corecel/Config.hh" 0014 0015 #include "corecel/Macros.hh" 0016 0017 namespace celeritas 0018 { 0019 //---------------------------------------------------------------------------// 0020 /*! 0021 * Temporarily store exception pointers. 0022 * 0023 * This is useful for storing multiple exceptions in unrelated loops (where one 0024 * exception shouldn't affect the program flow outside of the scope), 0025 * especially for OpenMP parallel execution, where exceptions cannot be 0026 * propagated. 0027 * \code 0028 MultiExceptionHandler capture_exception; 0029 #pragma omp parallel for 0030 for (size_type i = 0; i < data.states.size(); ++i) 0031 { 0032 CELER_TRY_HANDLE(step(TrackSlotId{i}), capture_exception); 0033 } 0034 log_and_rethrow(std::move(capture_exception)); 0035 * \endcode 0036 * 0037 * \note This class implements an OpenMP \c critical mutex, not a \c std 0038 * mutex. If using this class in a \c std::thread context, wrap the call 0039 * operator in a lambda with a \c std::scoped_lock . We could refactor as a 0040 * CRTP class with a protected \c push_back function that lets us specialize 0041 * the mutex implementation. 0042 */ 0043 class MultiExceptionHandler 0044 { 0045 public: 0046 //!@{ 0047 //! \name Type aliases 0048 using VecExceptionPtr = std::vector<std::exception_ptr>; 0049 //!@} 0050 0051 public: 0052 // Default all construct/copy/move 0053 MultiExceptionHandler() = default; 0054 CELER_DEFAULT_COPY_MOVE(MultiExceptionHandler); 0055 0056 // Terminate if destroyed without handling exceptions 0057 inline ~MultiExceptionHandler() noexcept(!CELERITAS_DEBUG); 0058 0059 // Thread-safe capture of the given exception 0060 void operator()(std::exception_ptr p); 0061 0062 //! Whether no exceptions have been stored (not thread safe) 0063 bool empty() const { return exceptions_.empty(); } 0064 0065 //! Release exceptions for someone else to process (not thread safe) 0066 VecExceptionPtr release() && { return std::move(exceptions_); } 0067 0068 private: 0069 VecExceptionPtr exceptions_; 0070 0071 [[noreturn]] void log_and_terminate() const; 0072 }; 0073 0074 //---------------------------------------------------------------------------// 0075 // FREE FUNCTIONS 0076 //---------------------------------------------------------------------------// 0077 namespace detail 0078 { 0079 // Private implementation function for throwing exceptions 0080 [[noreturn]] void log_and_rethrow_impl(MultiExceptionHandler&& exceptions); 0081 } // namespace detail 0082 0083 //---------------------------------------------------------------------------// 0084 /*! 0085 * Throw the first exception and log all the rest. 0086 * 0087 * All logged exceptions will be thrown using \c CELER_LOG_LOCAL(critical) . 0088 */ 0089 inline void log_and_rethrow(MultiExceptionHandler&& exceptions) 0090 { 0091 if (CELER_UNLIKELY(!exceptions.empty())) 0092 { 0093 detail::log_and_rethrow_impl(std::move(exceptions)); 0094 } 0095 } 0096 0097 //---------------------------------------------------------------------------// 0098 // INLINE FUNCTIONS 0099 //---------------------------------------------------------------------------// 0100 /*! 0101 * Terminate if destroyed without handling exceptions. 0102 */ 0103 MultiExceptionHandler::~MultiExceptionHandler() noexcept(!CELERITAS_DEBUG) 0104 { 0105 if (CELER_UNLIKELY(!exceptions_.empty())) 0106 { 0107 this->log_and_terminate(); 0108 } 0109 } 0110 0111 //---------------------------------------------------------------------------// 0112 } // namespace celeritas
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |