Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:09:43

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/ScopedSignalHandler.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <initializer_list>
0010 #include <utility>
0011 #include <vector>
0012 
0013 namespace celeritas
0014 {
0015 //---------------------------------------------------------------------------//
0016 /*!
0017  * Catch the given signal type within the scope of the handler.
0018  *
0019  * On instantiation with a non-empty argument, this class registers a signal
0020  * handler for the given signal. A class instance is true if and only if the
0021  * class is handling a signal. The instance's "call" operator will check and
0022  * return whether the assigned signal has been caught. The move-assign operator
0023  * can be used to unregister the handle.
0024  *
0025  * When the class exits scope, the signal for the active type will be cleared.
0026  *
0027  * Signal handling can be disabled by setting the environment variable \c
0028  * CELER_DISABLE_SIGNALS to a
0029  * non-empty value, but hopefully this will not be necessary because signal
0030  * handling should be used sparingly.
0031  *
0032  * \code
0033    #include <csignal>
0034 
0035    int main()
0036    {
0037       ScopedSignalHandler interrupted(SIGINT);
0038 
0039       while (true)
0040       {
0041           if (interrupted())
0042           {
0043               CELER_LOG(error) << "Interrupted";
0044               break;
0045           }
0046 
0047           if (stop_handling_for_whatever_reason())
0048           {
0049               // Clear handler
0050               interrupted = {};
0051           }
0052       }
0053       return interrupted() ? 1 : 0;
0054    }
0055    \endcode
0056  */
0057 class ScopedSignalHandler
0058 {
0059   public:
0060     //!@{
0061     //! \name Type aliases
0062     using signal_type = int;
0063     //!@}
0064 
0065   public:
0066     // Whether signals are enabled
0067     static bool allow_signals();
0068 
0069     // Raise a signal visible only to ScopedSignalHandler (for testing)
0070     static int raise(signal_type sig);
0071 
0072     //! Default to not handling any signals.
0073     ScopedSignalHandler() = default;
0074 
0075     // Handle the given signal type, asserting if it's already been raised
0076     explicit ScopedSignalHandler(signal_type);
0077 
0078     // Handle the given signal types
0079     explicit ScopedSignalHandler(std::initializer_list<signal_type>);
0080 
0081     // Release the given signal
0082     ~ScopedSignalHandler();
0083 
0084     // Check if signal was intercepted
0085     inline bool operator()() const;
0086 
0087     //! True if handling a signal
0088     explicit operator bool() const { return mask_ != 0; }
0089 
0090     // Move construct and assign to capture/release signal handling
0091     ScopedSignalHandler(ScopedSignalHandler const&) = delete;
0092     ScopedSignalHandler& operator=(ScopedSignalHandler const&) = delete;
0093     ScopedSignalHandler(ScopedSignalHandler&&) noexcept;
0094     ScopedSignalHandler& operator=(ScopedSignalHandler&&) noexcept;
0095     void swap(ScopedSignalHandler& other) noexcept;
0096 
0097   private:
0098     using HandlerPtr = void (*)(int);
0099     using PairSigHandle = std::pair<signal_type, HandlerPtr>;
0100     using VecSH = std::vector<PairSigHandle>;
0101 
0102     signal_type mask_{0};
0103     VecSH handles_;
0104 
0105     bool check_signal() const;
0106 };
0107 
0108 //---------------------------------------------------------------------------//
0109 // INLINE DEFINITIONS
0110 //---------------------------------------------------------------------------//
0111 /*!
0112  * Return whether a signal was intercepted.
0113  */
0114 bool ScopedSignalHandler::operator()() const
0115 {
0116     return *this && this->check_signal();
0117 }
0118 
0119 //---------------------------------------------------------------------------//
0120 }  // namespace celeritas