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